package com.turing.post.report.impl;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.ejb.EJB;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.naming.InitialContext;

import com.turing.post.account.util.AccountSystemAddTradDetail;
import com.turing.post.account.util.AccountSystemAddTradDetailDao;
import com.turing.post.capitalaccounts.util.BankAccountDetailDao;
import com.turing.post.capitalaccounts.util.SaleCapitalDetailDao;
import com.turing.post.cardmanagement.util.CardEventLog;
import com.turing.post.cardmanagement.util.CardEventLogDao;
import com.turing.post.cardmanagement.util.CardFace;
import com.turing.post.cardmanagement.util.CardFaceDao;
import com.turing.post.cardmanagement.util.IssueCardStockDetailDao;
import com.turing.post.cardmanagement.util.SaleCardStockDetailDao;
import com.turing.post.organization.util.CreditAccDetailDao;
import com.turing.post.organization.util.IssueBranch;
import com.turing.post.organization.util.IssueBranchDao;
import com.turing.post.organization.util.IssueCompany;
import com.turing.post.organization.util.IssueCompanyDao;
import com.turing.post.organization.util.Merchant;
import com.turing.post.organization.util.MerchantDao;
import com.turing.post.organization.util.SaleBranch;
import com.turing.post.organization.util.SaleBranchDao;
import com.turing.post.organization.util.SysBranchSubord;
import com.turing.post.organization.util.SysBranchSubordDao;
import com.turing.post.organization.util.Voucher;
import com.turing.post.organization.util.VoucherDao;
import com.turing.post.organization.util.VoucherStockDetailDao;
import com.turing.post.report.util.AccSysBranchCardDaySett;
import com.turing.post.report.util.AccSysBranchCardDaySettDao;
import com.turing.post.report.util.AccSysBranchDaySett;
import com.turing.post.report.util.AccSysBranchDaySettDao;
import com.turing.post.report.util.AccSysCardDaySettDao;
import com.turing.post.report.util.AccSysDaySettDao;
import com.turing.post.report.util.BranchDaySett;
import com.turing.post.report.util.BranchDaySettDao;
import com.turing.post.report.util.CreditDaySettlement;
import com.turing.post.report.util.CreditDaySettlementDao;
import com.turing.post.report.util.DaySettlementBusiness;
import com.turing.post.report.util.IncomeDaySettlement;
import com.turing.post.report.util.IncomeDaySettlementDao;
import com.turing.post.report.util.IssueCardStockDaySettlement;
import com.turing.post.report.util.IssueCardStockDaySettlementDao;
import com.turing.post.report.util.MerchantBusinessDaySettlement;
import com.turing.post.report.util.MerchantBusinessDaySettlementDao;
import com.turing.post.report.util.MerchantDaySettlement;
import com.turing.post.report.util.MerchantDaySettlementDao;
import com.turing.post.report.util.SaleCapitalDaySettlement;
import com.turing.post.report.util.SaleCapitalDaySettlementDao;
import com.turing.post.report.util.SaleCardStockDaySettlement;
import com.turing.post.report.util.SaleCardStockDaySettlementDao;
import com.turing.post.report.util.VoucherStockDaySettlement;
import com.turing.post.report.util.VoucherStockDaySettlementDao;
import com.turing.post.salesmanage.util.BranchDaySett_Obj;
import com.turing.post.salesmanage.util.DepositOrderPaidDetailDao;
import com.turing.post.salesmanage.util.RedempOrderDao;
import com.turing.post.salesmanage.util.SaleOrderPaidDetailDao;
import com.turing.post.transaction.util.MchAccDetailDao;
import com.turing.post.transaction.util.MchBsTypeTradDetailDao;
import com.turing.post.transaction.util.MchChkAccCtl;
import com.turing.post.transaction.util.MchChkAccCtlDao;
import com.turing.post.transaction.util.MchTradDetailDao;
import com.turing.post.util.PCPSApplicationException;
import com.turing.post.util.PCPSUtil;

@Stateless(mappedName = "report.impl.DaySettlementBusinessImpl")
@Remote
@Local
public class DaySettlementBusinessImpl implements DaySettlementBusiness {

	@EJB(mappedName = "organization.impl.SysBranchSubordDaoImpl")
	private SysBranchSubordDao sysBranchSubordDaoImpl;

	@EJB(mappedName = "cardmanagement.impl.CardFaceDaoImpl")
	private CardFaceDao cardFaceDaoImpl;

	@EJB(mappedName = "account.impl.AccountSystemAddTradDetailDaoImpl")
	private AccountSystemAddTradDetailDao accountSystemAddTradDetailDaoImpl;

	@EJB(mappedName = "report.impl.AccSysBranchCardDaySettDaoImpl")
	private AccSysBranchCardDaySettDao accSysBranchCardDaySettDaoImpl;

	@EJB(mappedName = "report.impl.AccSysBranchDaySettDaoImpl")
	private AccSysBranchDaySettDao accSysBranchDaySettDaoImpl;

	@EJB(mappedName = "report.impl.AccSysCardDaySettDaoImpl")
	private AccSysCardDaySettDao accSysCardDaySettDaoImpl;

	@EJB(mappedName = "report.impl.AccSysDaySettDaoImpl")
	private AccSysDaySettDao accSysDaySettDaoImpl;

	@EJB(mappedName = "capitalaccounts.impl.SaleCapitalDetailDaoImpl")
	private SaleCapitalDetailDao saleCapitalDetailDaoImpl;

	@EJB(mappedName = "capitalaccounts.impl.BankAccountDetailDaoImpl")
	private BankAccountDetailDao bankAccountDetailDaoImpl;

	@EJB(mappedName = "report.impl.SaleCapitalDaySettlementDaoImpl")
	private SaleCapitalDaySettlementDao saleCapitalDaySettlementDaoImpl;

	@EJB(mappedName = "cardmanagement.impl.IssueCardStockDetailDaoImpl")
	private IssueCardStockDetailDao issueCardStockDetailDaoImpl;

	@EJB(mappedName = "cardmanagement.impl.SaleCardStockDetailDaoImpl")
	private SaleCardStockDetailDao saleCardStockDetailDaoImpl;

	@EJB(mappedName = "report.impl.IssueCardStockDaySettlementDaoImpl")
	private IssueCardStockDaySettlementDao issueCardStockDaySettlementDaoImpl;

	@EJB(mappedName = "report.impl.SaleCardStockDaySettlementDaoImpl")
	private SaleCardStockDaySettlementDao saleCardStockDaySettlementDaoImpl;

	@EJB(mappedName = "transaction.impl.MchAccDetailDaoImpl")
	private MchAccDetailDao mchAccDetailDaoImpl;

	@EJB(mappedName = "report.impl.IncomeDaySettlementDaoImpl")
	private IncomeDaySettlementDao incomeDaySettlementDaoImpl;

	@EJB(mappedName = "organization.impl.MerchantDaoImpl")
	private MerchantDao merchantDaoImpl;

	@EJB(mappedName = "organization.impl.SaleBranchDaoImpl")
	private SaleBranchDao saleBranchDaoImpl;

	@EJB(mappedName = "organization.impl.IssueBranchDaoImpl")
	private IssueBranchDao issueBranchDaoImpl;

	@EJB(mappedName = "report.impl.MerchantDaySettlementDaoImpl")
	private MerchantDaySettlementDao merchantDaySettlementDaoImpl;

	@EJB(mappedName = "transaction.impl.MchBsTypeTradDetailDaoImpl")
	private MchBsTypeTradDetailDao mchBsTypeTradDetailDaoImpl;

	@EJB(mappedName = "report.impl.MerchantBusinessDaySettlementDaoImpl")
	private MerchantBusinessDaySettlementDao merchantBusinessDaySettlementDaoImpl;

	@EJB(mappedName = "transaction.impl.MchTradDetailDaoImpl")
	private MchTradDetailDao mchTradDetailDaoImpl;

	@EJB(mappedName = "organization.impl.IssueCompanyDaoImpl")
	private IssueCompanyDao issueCompanyDaoImpl;

	@EJB(mappedName = "transaction.impl.MchChkAccCtlDaoImpl")
	private MchChkAccCtlDao mchChkAccCtlDaoImpl;

	@EJB(mappedName = "report.impl.BranchDaySettDaoImpl")
	private BranchDaySettDao branchDaySettDaoImpl;

	@EJB(mappedName = "cardmanagement.impl.CardEventLogDaoImpl")
	private CardEventLogDao cardEventLogDaoImpl;

	@EJB(mappedName = "salesmanage.impl.SaleOrderPaidDetailDaoImpl")
	private SaleOrderPaidDetailDao saleOrderPaidDetailDaoImpl;

	@EJB(mappedName = "salesmanage.impl.DepositOrderPaidDetailDaoImpl")
	private DepositOrderPaidDetailDao depositOrderPaidDetailDaoImpl;

	@EJB(mappedName = "organization.impl.VoucherStockDetailDaoImpl")
	private VoucherStockDetailDao voucherStockDetailDaoImpl;

	@EJB(mappedName = "report.impl.VoucherStockDaySettlementDaoImpl")
	private VoucherStockDaySettlementDao voucherStockDaySettlementDaoImpl;

	@EJB(mappedName = "organization.impl.VoucherDaoImpl")
	private VoucherDao voucherDaoImpl;

	@EJB(mappedName = "report.impl.DaySettlementBusinessImpl")
	private DaySettlementBusiness daySettlementBusinessImpl;

	@EJB(mappedName = "report.impl.CreditDaySettlementDaoImpl")
	private CreditDaySettlementDao creditDaySettlementDaoImpl;

	@EJB(mappedName = "organization.impl.CreditAccDetailDaoImpl")
	private CreditAccDetailDao creditAccDetailDaoImpl;

	@EJB(mappedName = "salesmanage.impl.RedempOrderDaoImpl")
	private RedempOrderDao redempOrderDaoImpl;

	/**
	 * 根据发卡商号取所有的卡面图样
	 * 
	 * @param issueCompanyNo
	 * @return
	 */
	private Map<BigInteger, BigInteger> getAllCardFaceIdMapByIssueCompanyNo(
			String issueCompanyNo) {
		List<CardFace> all_cardface = cardFaceDaoImpl
				.getAllCardFaceByIssueCompanyNo(issueCompanyNo);

		Map<BigInteger, BigInteger> allCardFaceIdMap = new HashMap<BigInteger, BigInteger>();

		for (CardFace cc : all_cardface)
			allCardFaceIdMap.put(cc.getCardFaceId(), cc.getCardFaceId());

		return allCardFaceIdMap;
	}

	/**
	 * 根据发卡商号取所有的凭证种类
	 * 
	 * @param issueCompanyNo
	 * @return
	 */
	private Map<BigInteger, BigInteger> getAllVoucherIdMapByIssueCompanyNo(
			String issueCompanyNo) {
		List<Voucher> all_voucher = voucherDaoImpl
				.getAllVoucherByIssueCompanyNo(issueCompanyNo);

		Map<BigInteger, BigInteger> allVoucherIdMap = new HashMap<BigInteger, BigInteger>();

		for (Voucher cc : all_voucher)
			allVoucherIdMap.put(cc.getVoucherId(), cc.getVoucherId());

		return allVoucherIdMap;
	}

	/**
	 * 根据发卡商分支机构号或销售机构号取所有的销售分支机构号
	 * 
	 * @param branchNo
	 * @return
	 */
	private Map<String, String> getAllSaleBranchNoMapByBranchNo(String branchNo) {
		List<SysBranchSubord> all_salebranch = sysBranchSubordDaoImpl
				.getAllSaleBranchListByBranchNo(branchNo);

		Map<String, String> allSaleBranchNoMap = new HashMap<String, String>();

		for (SysBranchSubord sbs : all_salebranch)
			allSaleBranchNoMap.put(sbs.getSubBranchNo(), sbs.getSubBranchNo());

		return allSaleBranchNoMap;
	}

	/**
	 * 根据发卡商号或发卡商分支机构号取所有的下辖分支机构号
	 * 
	 * @param issueCompanyNo
	 * @return
	 */
	private Map<String, String> getAllIssueBranchNoMapByBranchNo(
			String issueCompanyNo) {
		List<SysBranchSubord> all_salebranch = sysBranchSubordDaoImpl
				.getAllIssueBranchListByBranchNo(issueCompanyNo);

		Map<String, String> allSaleBranchNoMap = new HashMap<String, String>();

		for (SysBranchSubord sbs : all_salebranch)
			allSaleBranchNoMap.put(sbs.getSubBranchNo(), sbs.getSubBranchNo());

		return allSaleBranchNoMap;
	}

	/**
	 * 删除某发卡商某日某销售机构列表下的所有数据(独立事务)
	 * 
	 * @param issueCompanyNo
	 * @param tranDate
	 * @param saleBranchNo
	 * @throws PCPSApplicationException
	 */
	private void removeAllAccSysBranchCardDaySettlementBySaleBranchNoAndTranDate(
			String issueCompanyNo, Date tranDate,
			Map<String, String> saleBranchNoMap)
			throws PCPSApplicationException {
		for (Map.Entry<String, String> saleBranchNoEntry : saleBranchNoMap
				.entrySet()) {
			accSysBranchCardDaySettDaoImpl
					.removeAllAccSysBranchCardDaySettByTranDate(issueCompanyNo,
							tranDate, saleBranchNoEntry.getKey());
		}
	}

	/**
	 * 删除某发卡商某日某销售机构列表下的所有数据(独立事务)
	 * 
	 * @param issueCompanyNo
	 * @param tranDate
	 * @param saleBranchNo
	 * @throws PCPSApplicationException
	 */
	private void removeAllAccSysBranchDaySettlementBySaleBranchNoAndTranDate(
			String issueCompanyNo, Date tranDate,
			Map<String, String> saleBranchNoMap)
			throws PCPSApplicationException {
		for (Map.Entry<String, String> saleBranchNoEntry : saleBranchNoMap
				.entrySet()) {
			accSysBranchDaySettDaoImpl.removeAllAccSysBranchDaySettByTranDate(
					issueCompanyNo, tranDate, saleBranchNoEntry.getKey());
		}
	}

	/**
	 * 产生KEY
	 * 
	 * @param saleBranchNo
	 * @param cardClassId
	 * @return
	 */
	private String getSaleBranchNoCardClassIdKey(String saleBranchNo,
			BigInteger cardClassId) {
		StringBuilder keysb = new StringBuilder();
		keysb.append(saleBranchNo);
		keysb.append("_");
		keysb.append(cardClassId);
		return keysb.toString();
	}

	/**
	 * 取上日余额
	 * 
	 * @param issueCompanyNo
	 * @param tranDate
	 * @param saleBranchNo
	 * @param cardClassicId
	 * @return
	 */
	private BigInteger getAccSysBranchCardDaySettLastBalance(
			String issueCompanyNo, Date tranDate, String saleBranchNo,
			BigInteger cardClassicId) {
		Date lastTranDate = accSysBranchCardDaySettDaoImpl.getMaxTranDate(
				issueCompanyNo, tranDate, saleBranchNo, cardClassicId);
		if (lastTranDate == null)
			return BigInteger.ZERO;

		AccSysBranchCardDaySett qry_asbcds = new AccSysBranchCardDaySett();

		qry_asbcds.setIssueCompanyNo(issueCompanyNo);
		qry_asbcds.setTranDate(lastTranDate);
		qry_asbcds.setSaleBranchNo(saleBranchNo);
		qry_asbcds.setCardClassicId(cardClassicId);

		AccSysBranchCardDaySett ascds = accSysBranchCardDaySettDaoImpl
				.getAccSysBranchCardDaySettByKey(qry_asbcds);

		return ascds == null ? BigInteger.ZERO : ascds.getBalance();
	}

	/**
	 * 产生销售机构卡种类按交易类型分组数据
	 * 
	 * @param issueCompanyNo
	 * @param tranDate
	 * @param issueBranchNo
	 * @return
	 */
	private Map<String, AccSysBranchCardDaySett> getAllSumAccountSystemAddTradDetailByBranchCardClassicGroup(
			String issueCompanyNo, Date tranDate, String issueBranchNo)
			throws PCPSApplicationException {
		// 取汇总数据
		List<AccountSystemAddTradDetail> asatd_sum_list = accountSystemAddTradDetailDaoImpl
				.sumAllAccountSystemAddTradDetailByBranchAndCardClassic(
						issueCompanyNo, tranDate, issueBranchNo);

		Map<String, AccSysBranchCardDaySett> map = new HashMap<String, AccSysBranchCardDaySett>();

		for (AccountSystemAddTradDetail asatd : asatd_sum_list) {
			// 不关心卡种类为空的数据
			if (asatd.getCardClassicId() == null)
				continue;
			String key = getSaleBranchNoCardClassIdKey(asatd.getOpenBranchNo(),
					asatd.getCardClassicId());

			AccSysBranchCardDaySett al = new AccSysBranchCardDaySett();
			al.setIssueCompanyNo(issueCompanyNo);
			al.setTranDate(tranDate);
			al.setSaleBranchNo(asatd.getOpenBranchNo());
			al.setCardClassicId(asatd.getCardClassicId());
			al.setLastBalance(getAccSysBranchCardDaySettLastBalance(
					issueCompanyNo, tranDate, asatd.getOpenBranchNo(), asatd
							.getCardClassicId()));
			al.setSaleAmount(asatd.getSaleAmount());
			al.setDepositAmount(asatd.getDepositAmount());
			al.setConsumeAmount(asatd.getConsumeAmount());
			al.setRedemingAmount(asatd.getRedemingAmount());
			al.setFeeAmount(asatd.getFeeAmount());
			al.setAdjustAmount(asatd.getAdjustAmount());
			al.setBalance(BigInteger.ZERO);

			// 重新计算本日余额
			al.reCalcBalance();

			map.put(key, al);
		}

		return map;
	}

	/**
	 * 创建有效的销售机构卡种类日结数据
	 * 
	 * @param asbcds
	 * @throws PCPSApplicationException
	 */
	private void createAccSysBranchCardDaySett(AccSysBranchCardDaySett asbcds)
			throws PCPSApplicationException {
		if (asbcds == null)
			return;

		if (BigInteger.ZERO.equals(asbcds.getLastBalance())
				&& BigInteger.ZERO.equals(asbcds.getSaleAmount())
				&& BigInteger.ZERO.equals(asbcds.getDepositAmount())
				&& BigInteger.ZERO.equals(asbcds.getConsumeAmount())
				&& BigInteger.ZERO.equals(asbcds.getRedemingAmount())
				&& BigInteger.ZERO.equals(asbcds.getFeeAmount())
				&& BigInteger.ZERO.equals(asbcds.getAdjustAmount())
				&& BigInteger.ZERO.equals(asbcds.getBalance()))
			return;

		PCPSUtil.Log(String.format("AccSysBranchCardDaySett(%s,%s,%s)", asbcds
				.getSaleBranchNo(), PCPSUtil.getPackedYMDString(asbcds
				.getTranDate()), asbcds.getCardClassicId().toString()));

		accSysBranchCardDaySettDaoImpl.insert(asbcds);
	}

	/**
	 * 创建有效的销售机构日结数据
	 * 
	 * @param asbcds
	 * @throws PCPSApplicationException
	 */
	private void createAccSysBranchDaySett(AccSysBranchDaySett asbcds)
			throws PCPSApplicationException {
		if (asbcds == null)
			return;

		if (BigInteger.ZERO.equals(asbcds.getLastBalance())
				&& BigInteger.ZERO.equals(asbcds.getSaleAmount())
				&& BigInteger.ZERO.equals(asbcds.getDepositAmount())
				&& BigInteger.ZERO.equals(asbcds.getConsumeAmount())
				&& BigInteger.ZERO.equals(asbcds.getRedemingAmount())
				&& BigInteger.ZERO.equals(asbcds.getFeeAmount())
				&& BigInteger.ZERO.equals(asbcds.getAdjustAmount())
				&& BigInteger.ZERO.equals(asbcds.getBalance()))
			return;

		accSysBranchDaySettDaoImpl.insert(asbcds);
	}

	/**
	 * 产生某发卡商某日某发卡商分支机构下属销售机构卡种类日结数据
	 * 
	 * @param issueCompanyNo
	 *            发卡商NO
	 * @param tranDate
	 *            帐务日期
	 * @param issueBranchNo
	 *            发卡商分支机构
	 * @throws PCPSApplicationException
	 */
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public void generateAccSysBranchCardDaySettlement(String issueCompanyNo,
			Date tranDate, String issueBranchNo)
			throws PCPSApplicationException {

		// 干净的日期
		tranDate = PCPSUtil.getZeroedHMS(tranDate);

		// 取汇总数据
		Map<String, AccSysBranchCardDaySett> asbcds_today = getAllSumAccountSystemAddTradDetailByBranchCardClassicGroup(
				issueCompanyNo, tranDate, issueBranchNo);

		// 取所有的卡种类数据
		Map<BigInteger, BigInteger> allCardClassicIdMap = getAllCardFaceIdMapByIssueCompanyNo(issueCompanyNo);

		// 所有的销售分支机构
		Map<String, String> allSaleBranchNoMap = getAllSaleBranchNoMapByBranchNo(issueBranchNo);

		// 先删除
		removeAllAccSysBranchCardDaySettlementBySaleBranchNoAndTranDate(
				issueCompanyNo, tranDate, allSaleBranchNoMap);

		String saleBranchNo = null;
		BigInteger cardClassicId = null;
		String key = null;

		// 循环产生
		for (Map.Entry<String, String> saleBranch : allSaleBranchNoMap
				.entrySet()) {
			saleBranchNo = saleBranch.getKey();
			for (Map.Entry<BigInteger, BigInteger> cardClassic : allCardClassicIdMap
					.entrySet()) {
				cardClassicId = cardClassic.getKey();
				key = getSaleBranchNoCardClassIdKey(saleBranchNo, cardClassicId);
				AccSysBranchCardDaySett asbcds = asbcds_today.remove(key);
				// 当日有数据
				if (asbcds != null) {
					createAccSysBranchCardDaySett(asbcds);
					continue;
				}
				// 当日无数据
				Date lastTranDate = accSysBranchCardDaySettDaoImpl
						.getMaxTranDate(issueCompanyNo, tranDate, saleBranchNo,
								cardClassicId);
				// 前日无数据
				if (lastTranDate == null)
					continue;

				AccSysBranchCardDaySett last_asbcds = new AccSysBranchCardDaySett();

				last_asbcds.setIssueCompanyNo(issueCompanyNo);
				last_asbcds.setTranDate(lastTranDate);
				last_asbcds.setSaleBranchNo(saleBranchNo);
				last_asbcds.setCardClassicId(cardClassicId);

				AccSysBranchCardDaySett olast_asbcds = accSysBranchCardDaySettDaoImpl
						.getAccSysBranchCardDaySettByKey(last_asbcds);
				if (olast_asbcds != null) {
					last_asbcds.setTranDate(tranDate);
					BigInteger lastBalance = olast_asbcds.getBalance();
					last_asbcds.setLastBalance(lastBalance);
					last_asbcds.setSaleAmount(BigInteger.ZERO);
					last_asbcds.setDepositAmount(BigInteger.ZERO);
					last_asbcds.setConsumeAmount(BigInteger.ZERO);
					last_asbcds.setRedemingAmount(BigInteger.ZERO);
					last_asbcds.setFeeAmount(BigInteger.ZERO);
					last_asbcds.setAdjustAmount(BigInteger.ZERO);
					last_asbcds.setBalance(lastBalance);
					// 迁移前日数据到今日
					createAccSysBranchCardDaySett(last_asbcds);
				}
			}
		}
	}

	/**
	 * 取上日余额
	 * 
	 * @param issueCompanyNo
	 * @param tranDate
	 * @param saleBranchNo
	 * @return
	 */
	private BigInteger getAccSysBranchDaySettLastBalance(String issueCompanyNo,
			Date tranDate, String saleBranchNo) {
		Date lastTranDate = accSysBranchDaySettDaoImpl.getMaxTranDate(
				issueCompanyNo, tranDate, saleBranchNo);
		if (lastTranDate == null)
			return BigInteger.ZERO;

		AccSysBranchDaySett qry_asbcds = new AccSysBranchDaySett();

		qry_asbcds.setIssueCompanyNo(issueCompanyNo);
		qry_asbcds.setTranDate(lastTranDate);
		qry_asbcds.setSaleBranchNo(saleBranchNo);

		AccSysBranchDaySett ascds = accSysBranchDaySettDaoImpl
				.getAccSysBranchDaySettByKey(qry_asbcds);

		return ascds == null ? BigInteger.ZERO : ascds.getBalance();
	}

	/**
	 * 产生销售机构按交易类型分组数据
	 * 
	 * @param issueCompanyNo
	 * @param tranDate
	 * @param issueBranchNo
	 * @return
	 */
	private Map<String, AccSysBranchDaySett> getAllSumAccountSystemAddTradDetailByBranchGroup(
			String issueCompanyNo, Date tranDate, String issueBranchNo)
			throws PCPSApplicationException {
		// 取汇总数据
		List<AccountSystemAddTradDetail> asatd_sum_list = accountSystemAddTradDetailDaoImpl
				.sumAllAccountSystemAddTradDetailByBranch(issueCompanyNo,
						tranDate, issueBranchNo);

		Map<String, AccSysBranchDaySett> map = new HashMap<String, AccSysBranchDaySett>();

		for (AccountSystemAddTradDetail asatd : asatd_sum_list) {
			String key = asatd.getOpenBranchNo();
			AccSysBranchDaySett al = new AccSysBranchDaySett();
			al.setIssueCompanyNo(issueCompanyNo);
			al.setTranDate(tranDate);
			al.setSaleBranchNo(asatd.getOpenBranchNo());
			al.setLastBalance(getAccSysBranchDaySettLastBalance(issueCompanyNo,
					tranDate, asatd.getOpenBranchNo()));
			al.setSaleAmount(asatd.getSaleAmount());
			al.setDepositAmount(asatd.getDepositAmount());
			al.setConsumeAmount(asatd.getConsumeAmount());
			al.setRedemingAmount(asatd.getRedemingAmount());
			al.setFeeAmount(asatd.getFeeAmount());
			al.setAdjustAmount(asatd.getAdjustAmount());
			al.setBalance(BigInteger.ZERO);

			// 重新计算本日余额
			al.reCalcBalance();

			map.put(key, al);
		}

		return map;
	}

	/**
	 * 产生某发卡商某日某销售商下属销售机构的日结数据
	 * 
	 * @param issueCompanyNo
	 *            发卡商NO
	 * @param tranDate
	 *            帐务日期
	 * @param issueBranchNo
	 *            发卡商分支机构
	 * @throws PCPSApplicationException
	 */
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public void generateAccSysBranchDaySettlement(String issueCompanyNo,
			Date tranDate, String issueBranchNo)
			throws PCPSApplicationException {
		// 干净的日期
		tranDate = PCPSUtil.getZeroedHMS(tranDate);

		// 取汇总数据
		Map<String, AccSysBranchDaySett> asbcds_today = getAllSumAccountSystemAddTradDetailByBranchGroup(
				issueCompanyNo, tranDate, issueBranchNo);

		// 所有的销售分支机构
		Map<String, String> allSaleBranchNoMap = getAllSaleBranchNoMapByBranchNo(issueBranchNo);

		// 先删除
		removeAllAccSysBranchDaySettlementBySaleBranchNoAndTranDate(
				issueCompanyNo, tranDate, allSaleBranchNoMap);

		String saleBranchNo = null;

		// 循环产生
		for (Map.Entry<String, String> saleBranch : allSaleBranchNoMap
				.entrySet()) {
			saleBranchNo = saleBranch.getKey();

			AccSysBranchDaySett asbcds = asbcds_today.remove(saleBranchNo);
			// 当日有数据
			if (asbcds != null) {
				createAccSysBranchDaySett(asbcds);
				continue;
			}
			// 当日无数据
			Date lastTranDate = accSysBranchDaySettDaoImpl.getMaxTranDate(
					issueCompanyNo, tranDate, saleBranchNo);
			// 前日无数据
			if (lastTranDate == null)
				continue;

			AccSysBranchDaySett last_asbcds = new AccSysBranchDaySett();

			last_asbcds.setIssueCompanyNo(issueCompanyNo);
			last_asbcds.setTranDate(lastTranDate);
			last_asbcds.setSaleBranchNo(saleBranchNo);

			AccSysBranchDaySett olast_asbcds = accSysBranchDaySettDaoImpl
					.getAccSysBranchDaySettByKey(last_asbcds);
			if (olast_asbcds != null) {
				last_asbcds.setTranDate(tranDate);
				BigInteger lastBalance = olast_asbcds.getBalance();
				last_asbcds.setLastBalance(lastBalance);
				last_asbcds.setSaleAmount(BigInteger.ZERO);
				last_asbcds.setDepositAmount(BigInteger.ZERO);
				last_asbcds.setConsumeAmount(BigInteger.ZERO);
				last_asbcds.setRedemingAmount(BigInteger.ZERO);
				last_asbcds.setFeeAmount(BigInteger.ZERO);
				last_asbcds.setAdjustAmount(BigInteger.ZERO);
				last_asbcds.setBalance(lastBalance);
				// 迁移前日数据到今日
				createAccSysBranchDaySett(last_asbcds);
			}
		}
	}

	/**
	 * 删除某发卡商某日所有的卡种类日结数据(独立事务)
	 * 
	 * @param issueCompanyNo
	 * @param tranDate
	 * @throws PCPSApplicationException
	 */
	private void removeAllAccSysCardDaySettlementByTranDate(
			String issueCompanyNo, Date tranDate) {
		accSysCardDaySettDaoImpl.removeAllAccSysCardDaySettByTranDate(
				issueCompanyNo, tranDate);
	}

	/**
	 * 产生某发卡商某日卡种类日结数据
	 * 
	 * @param issueCompanyNo
	 *            发卡商NO
	 * @param tranDate
	 *            帐务日期
	 * @throws PCPSApplicationException
	 */
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public void generateAccSysCardDaySettlement(String issueCompanyNo,
			Date tranDate) throws PCPSApplicationException {

		// 删除某发卡商某日所有的卡种类日结数据(独立事务)
		removeAllAccSysCardDaySettlementByTranDate(issueCompanyNo, tranDate);

		// 产生汇总数据
		accSysCardDaySettDaoImpl.generateAccSysCardDaySett(issueCompanyNo,
				tranDate);
	}

	/**
	 * 删除某发卡商某日所有的日结数据(独立事务)
	 * 
	 * @param issueCompanyNo
	 * @param tranDate
	 * @throws PCPSApplicationException
	 */
	private void removeAllAccSysDaySettlementByTranDate(String issueCompanyNo,
			Date tranDate) {
		accSysDaySettDaoImpl.removeAllAccSysDaySettByTranDate(issueCompanyNo,
				tranDate);
	}

	/**
	 * 产生某发卡商某日的日结数据
	 * 
	 * @param issueCompanyNo
	 *            发卡商NO
	 * @param tranDate
	 *            帐务日期
	 * @throws PCPSApplicationException
	 */
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public void generateAccSysDaySettlement(String issueCompanyNo, Date tranDate)
			throws PCPSApplicationException {

		// 删除某发卡商某日所有的日结数据(独立事务)
		removeAllAccSysDaySettlementByTranDate(issueCompanyNo, tranDate);

		// 产生汇总数据
		accSysDaySettDaoImpl.generateAccSysDaySett(issueCompanyNo, tranDate);
	}

	/**
	 * 删除某发卡商某日所有销售机构的资金日结数据(独立事务)
	 * 
	 * @param issueCompanyNo
	 * @param tranDate
	 * @throws PCPSApplicationException
	 */
	private void removeAllSaleCapitalDaySettlementByTranDate(
			String issueCompanyNo, Date tranDate) {
		saleCapitalDaySettlementDaoImpl
				.removeAllSaleCapitalDaySettlementByTranDate(issueCompanyNo,
						tranDate);
	}

	/**
	 * 取某销售机构上日资金日结数据
	 * 
	 * @param saleBranchNo
	 * @param tranDate
	 * @return
	 */
	private SaleCapitalDaySettlement getLastSaleCapitalDaySettlements(
			String saleBranchNo, Date tranDate) {
		Date lastTranDate = saleCapitalDaySettlementDaoImpl.getMaxTranDate(
				tranDate, saleBranchNo);
		if (lastTranDate == null) {
			SaleCapitalDaySettlement scds = new SaleCapitalDaySettlement();
			scds.setCash(BigInteger.ZERO);
			scds.setCredit(BigInteger.ZERO);
			return scds;
		}

		SaleCapitalDaySettlement qry_scds = new SaleCapitalDaySettlement();

		qry_scds.setSaleBranchNo(saleBranchNo);
		qry_scds.setTranDate(lastTranDate);

		return saleCapitalDaySettlementDaoImpl
				.getSaleCapitalDaySettlementByKey(qry_scds);
	}

	private List<SaleCapitalDaySettlement> sumAllSaleCapitalDaySettlementByBranch(
			String issueCompanyNo, Date tranDate) {
		List<Object[]> obj_list = saleCapitalDetailDaoImpl
				.sumAllSaleCapitalDaySettlementByBranch(issueCompanyNo,
						tranDate);
		// 类型转换
		List<SaleCapitalDaySettlement> asatd_list = new ArrayList<SaleCapitalDaySettlement>();
		for (Object[] objarr : obj_list) {
			SaleCapitalDaySettlement scds = new SaleCapitalDaySettlement();
			scds.setSaleBranchNo(objarr[0].toString());
			scds.setTranDate(tranDate);
			scds.setCreditDeposit(new BigInteger(objarr[1].toString()));
			scds.setCreditWithdraw(new BigInteger(objarr[2].toString()));
			scds.setCashDeposit(new BigInteger(objarr[3].toString()));
			scds.setCashWithdraw(new BigInteger(objarr[4].toString()));
			asatd_list.add(scds);
		}

		return asatd_list;

	}

	/**
	 * 产生销售机构按交易类型分组数据
	 * 
	 * @param issueCompanyNo
	 * @param tranDate
	 * @param saleCompanyNo
	 * @return
	 */
	private Map<String, SaleCapitalDaySettlement> getAllSumSaleCapitalDaySettlementByBranchGroup(
			String issueCompanyNo, Date tranDate)
			throws PCPSApplicationException {
		// 取汇总数据
		List<SaleCapitalDaySettlement> asatd_sum_list = sumAllSaleCapitalDaySettlementByBranch(
				issueCompanyNo, tranDate);

		Map<String, SaleCapitalDaySettlement> map = new HashMap<String, SaleCapitalDaySettlement>();

		for (SaleCapitalDaySettlement scds : asatd_sum_list) {
			SaleCapitalDaySettlement last_scds = getLastSaleCapitalDaySettlements(
					scds.getSaleBranchNo(), scds.getTranDate());
			scds.setLastCredit(last_scds.getCredit());
			scds.setLastCash(last_scds.getCash());
			scds.setCredit(BigInteger.ZERO);
			scds.setCash(BigInteger.ZERO);

			// 重新计算本日信用度及现金库余额
			scds.reCalcToday();

			map.put(scds.getSaleBranchNo(), scds);
		}

		return map;
	}

	/**
	 * 创建有效的销售机构资金日结数据
	 * 
	 * @param asbcds
	 * @throws PCPSApplicationException
	 */
	private void createSaleCapitalDaySettlement(SaleCapitalDaySettlement scds)
			throws PCPSApplicationException {
		if (scds == null)
			return;

		if (BigInteger.ZERO.equals(scds.getLastCredit())
				&& BigInteger.ZERO.equals(scds.getCreditDeposit())
				&& BigInteger.ZERO.equals(scds.getCreditWithdraw())
				&& BigInteger.ZERO.equals(scds.getCredit())
				&& BigInteger.ZERO.equals(scds.getLastCash())
				&& BigInteger.ZERO.equals(scds.getCashDeposit())
				&& BigInteger.ZERO.equals(scds.getCashWithdraw())
				&& BigInteger.ZERO.equals(scds.getCash()))
			return;

		saleCapitalDaySettlementDaoImpl.insert(scds);
	}

	/**
	 * 产生某发卡商某日的销售机构资金日结数据
	 * 
	 * @param issueCompanyNo
	 *            发卡商NO
	 * @param tranDate
	 *            帐务日期
	 * @throws PCPSApplicationException
	 */
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public void generateSaleCapitalDaySettlement(String issueCompanyNo,
			Date tranDate) throws PCPSApplicationException {

		// 干净的日期
		tranDate = PCPSUtil.getZeroedHMS(tranDate);

		// 取汇总数据
		Map<String, SaleCapitalDaySettlement> scds_today = getAllSumSaleCapitalDaySettlementByBranchGroup(
				issueCompanyNo, tranDate);

		// 所有的销售分支机构
		Map<String, String> allSaleBranchNoMap = getAllSaleBranchNoMapByBranchNo(issueCompanyNo);

		// 删除某发卡商某日所有销售机构资金日结数据
		PCPSUtil.Log("删除某发卡商某日所有销售机构资金日结数据-------1--");
		removeAllSaleCapitalDaySettlementByTranDate(issueCompanyNo, tranDate);

		String saleBranchNo = null;

		// 循环产生
		for (Map.Entry<String, String> saleBranch : allSaleBranchNoMap
				.entrySet()) {
			saleBranchNo = saleBranch.getKey();
			PCPSUtil.Log("开始处理机构-------2--" + saleBranchNo);
			SaleCapitalDaySettlement scds = scds_today.remove(saleBranchNo);
			// 当日有数据
			if (scds != null) {
				PCPSUtil.Log("当日有数据-------3--" + saleBranchNo);
				createSaleCapitalDaySettlement(scds);
				continue;
			}
			// 当日无数据
			PCPSUtil.Log("当日无数据-------4--" + saleBranchNo);
			Date lastTranDate = saleCapitalDaySettlementDaoImpl.getMaxTranDate(
					tranDate, saleBranchNo);
			// 前日无数据
			PCPSUtil.Log("前日无数据-------5--" + saleBranchNo);
			if (lastTranDate == null)
				continue;

			SaleCapitalDaySettlement last_scds = new SaleCapitalDaySettlement();

			last_scds.setTranDate(lastTranDate);
			last_scds.setSaleBranchNo(saleBranchNo);

			PCPSUtil.Log("获取扎帐操作对象-------6--" + saleBranchNo);
			SaleCapitalDaySettlement olast_scds = saleCapitalDaySettlementDaoImpl
					.getSaleCapitalDaySettlementByKey(last_scds);
			if (olast_scds != null) {
				PCPSUtil.Log("进入扎帐操作-------7--" + saleBranchNo);
				last_scds.setTranDate(tranDate);
				BigInteger lastCredit = olast_scds.getCredit();

				last_scds.setLastCredit(lastCredit);
				last_scds.setCreditDeposit(BigInteger.ZERO);
				last_scds.setCreditWithdraw(BigInteger.ZERO);
				last_scds.setCredit(lastCredit);

				BigInteger lastCash = last_scds.getCash();
				last_scds.setLastCash(lastCash);
				last_scds.setCashDeposit(BigInteger.ZERO);
				last_scds.setCashWithdraw(BigInteger.ZERO);
				last_scds.setCash(lastCash);

				// 迁移前日数据到今日
				PCPSUtil.Log("迁移前日数据到今日-------8--" + saleBranchNo);
				createSaleCapitalDaySettlement(last_scds);
			}
		}
	}

	/**
	 * 取某销售机构上日资金日结数据
	 * 
	 * @param issueBranchNo
	 * @param tranDate
	 * @param cardClassicId
	 * @param cardParValueId
	 * @return
	 */
	private IssueCardStockDaySettlement getLastIssueCardStockDaySettlement(
			String issueBranchNo, Date tranDate, BigInteger cardFaceId) {
		Date lastTranDate = issueCardStockDaySettlementDaoImpl.getMaxTranDate(
				issueBranchNo, tranDate, cardFaceId);
		if (lastTranDate == null) {
			IssueCardStockDaySettlement scds = new IssueCardStockDaySettlement();
			scds.setBalance(BigInteger.ZERO);
			return scds;
		}

		IssueCardStockDaySettlement qry_scds = new IssueCardStockDaySettlement();

		qry_scds.setIssueBranchNo(issueBranchNo);
		qry_scds.setTranDate(lastTranDate);
		qry_scds.setCardFaceId(cardFaceId);

		return issueCardStockDaySettlementDaoImpl
				.getIssueCardStockDaySettlementByKey(qry_scds);
	}

	/**
	 * 发卡商分支机构卡库存日结表KEY
	 * 
	 * @param icsds
	 * @return
	 */
	private String getCardStockDaySettlementKey(String issueBranchNo,
			BigInteger cardFaceId) {
		StringBuilder sb = new StringBuilder();
		sb.append(issueBranchNo);
		sb.append("_");
		sb.append(cardFaceId);
		return sb.toString();
	}

	private List<IssueCardStockDaySettlement> sumAllIssueCardStockDaySettlementByTranDate(
			String issueCompanyNo, Date tranDate) {
		List<Object[]> obj_list = issueCardStockDetailDaoImpl
				.sumAllIssueCardStockDaySettlementByTranDate(issueCompanyNo,
						tranDate);
		// 类型转换
		List<IssueCardStockDaySettlement> all = new ArrayList<IssueCardStockDaySettlement>();
		for (Object[] objarr : obj_list) {
			IssueCardStockDaySettlement icsds = new IssueCardStockDaySettlement();
			icsds.setIssueBranchNo(objarr[0].toString());
			icsds.setTranDate(tranDate);
			icsds.setCardFaceId(new BigInteger(objarr[1].toString()));
			icsds.setLastBalance(BigInteger.ZERO);
			icsds.setInitialIn(new BigInteger(objarr[2].toString()));
			icsds.setTransferIn(new BigInteger(objarr[3].toString()));
			icsds.setTransferOut(new BigInteger(objarr[4].toString()));
			icsds.setSurplusIn(new BigInteger(objarr[5].toString()));
			icsds.setLossDamageOut(new BigInteger(objarr[6].toString()));
			icsds.setBalance(BigInteger.ZERO);
			all.add(icsds);
		}
		return all;
	}

	/**
	 * 产生发卡商分支机构按卡种类面值分组数据
	 * 
	 * @param issueCompanyNo
	 * @param tranDate
	 * @return
	 */
	private Map<String, IssueCardStockDaySettlement> getAllIssueCardStockDaySettlementGroup(
			String issueCompanyNo, Date tranDate)
			throws PCPSApplicationException {
		// 取汇总数据
		List<IssueCardStockDaySettlement> asatd_sum_list = sumAllIssueCardStockDaySettlementByTranDate(
				issueCompanyNo, tranDate);

		Map<String, IssueCardStockDaySettlement> map = new HashMap<String, IssueCardStockDaySettlement>();

		for (IssueCardStockDaySettlement scds : asatd_sum_list) {
			IssueCardStockDaySettlement last_scds = getLastIssueCardStockDaySettlement(
					scds.getIssueBranchNo(), scds.getTranDate(), scds
							.getCardFaceId());
			scds.setLastBalance(last_scds.getBalance());

			// 重新计算本日库存余额
			scds.reCalcBalance();

			map.put(getCardStockDaySettlementKey(scds.getIssueBranchNo(), scds
					.getCardFaceId()), scds);
		}

		return map;
	}

	/**
	 * 删除某发卡商某日所有分支机构库存日结数据(独立事务)
	 * 
	 * @param issueCompanyNo
	 * @param tranDate
	 * @throws PCPSApplicationException
	 */
	public void removeAllIssueCardStockDaySettlementByTranDate(
			String issueCompanyNo, Date tranDate) {
		issueCardStockDaySettlementDaoImpl
				.removeAllIssueCardStockDaySettlementByTranDate(issueCompanyNo,
						tranDate);
	}

	/**
	 * 创建有效的发卡商分支机构卡库存日结数据
	 * 
	 * @param asbcds
	 * @throws PCPSApplicationException
	 */
	private void createIssueCardStockDaySettlement(
			IssueCardStockDaySettlement scds) throws PCPSApplicationException {
		if (scds == null)
			return;

		if (BigInteger.ZERO.equals(scds.getLastBalance())
				&& BigInteger.ZERO.equals(scds.getInitialIn())
				&& BigInteger.ZERO.equals(scds.getTransferIn())
				&& BigInteger.ZERO.equals(scds.getTransferOut())
				&& BigInteger.ZERO.equals(scds.getSurplusIn())
				&& BigInteger.ZERO.equals(scds.getLossDamageOut())
				&& BigInteger.ZERO.equals(scds.getBalance()))
			return;

		issueCardStockDaySettlementDaoImpl.insert(scds);
	}

	/**
	 * 产生某发卡商某日所有分支机构的卡库存日结数据
	 * 
	 * @param issueCompanyNo
	 *            发卡商NO
	 * @param tranDate
	 *            帐务日期
	 * @throws PCPSApplicationException
	 */
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public void generateIssueCardStockDaySettlement(String issueCompanyNo,
			Date tranDate) throws PCPSApplicationException {
		// 干净的日期
		tranDate = PCPSUtil.getZeroedHMS(tranDate);

		// 取汇总数据
		Map<String, IssueCardStockDaySettlement> scds_today = getAllIssueCardStockDaySettlementGroup(
				issueCompanyNo, tranDate);

		// 所有的发卡商分支机构
		Map<String, String> allIssueBranchNoMap = getAllIssueBranchNoMapByBranchNo(issueCompanyNo);

		// 取所有的卡面ID数据
		Map<BigInteger, BigInteger> allCardFaceIdMap = getAllCardFaceIdMapByIssueCompanyNo(issueCompanyNo);

		// 删除某发卡商某日所有分支机构库存日结数据
		removeAllIssueCardStockDaySettlementByTranDate(issueCompanyNo, tranDate);

		String issueBranchNo = null;
		BigInteger cardFaceId = null;
		String key = null;

		// 循环产生
		// 发卡商分支机构循环
		for (Map.Entry<String, String> issueBranch : allIssueBranchNoMap
				.entrySet()) {
			issueBranchNo = issueBranch.getKey();
			// 卡面图样循环
			for (Map.Entry<BigInteger, BigInteger> cardFace : allCardFaceIdMap
					.entrySet()) {
				cardFaceId = cardFace.getKey();
				key = getCardStockDaySettlementKey(issueBranchNo, cardFaceId);
				IssueCardStockDaySettlement scds = scds_today.remove(key);
				// 当日有数据
				if (scds != null) {
					createIssueCardStockDaySettlement(scds);
					continue;
				}
				// 当日无数据
				Date lastTranDate = issueCardStockDaySettlementDaoImpl
						.getMaxTranDate(issueBranchNo, tranDate, cardFaceId);
				// 前日无数据
				if (lastTranDate == null)
					continue;

				IssueCardStockDaySettlement last_scds = new IssueCardStockDaySettlement();

				last_scds.setTranDate(lastTranDate);
				last_scds.setIssueBranchNo(issueBranchNo);
				last_scds.setCardFaceId(cardFaceId);

				IssueCardStockDaySettlement olast_scds = issueCardStockDaySettlementDaoImpl
						.getIssueCardStockDaySettlementByKey(last_scds);
				if (olast_scds != null) {
					last_scds.setTranDate(tranDate);
					BigInteger lastBalance = olast_scds.getBalance();

					last_scds.setLastBalance(lastBalance);
					last_scds.setInitialIn(BigInteger.ZERO);
					last_scds.setTransferIn(BigInteger.ZERO);
					last_scds.setTransferOut(BigInteger.ZERO);
					last_scds.setSurplusIn(BigInteger.ZERO);
					last_scds.setLossDamageOut(BigInteger.ZERO);

					last_scds.setBalance(lastBalance);

					// 迁移前日数据到今日
					createIssueCardStockDaySettlement(last_scds);
				}
			}
		}
	}

	/**
	 * 取某销售机构上日卡库存日结数据
	 * 
	 * @param saleBranchNo
	 * @param tranDate
	 * @param cardFaceId
	 * @return
	 */
	private SaleCardStockDaySettlement getLastSaleCardStockDaySettlement(
			String saleBranchNo, Date tranDate, BigInteger cardFaceId) {
		Date lastTranDate = saleCardStockDaySettlementDaoImpl.getMaxTranDate(
				saleBranchNo, tranDate, cardFaceId);
		if (lastTranDate == null) {
			SaleCardStockDaySettlement scds = new SaleCardStockDaySettlement();
			scds.setBalance(BigInteger.ZERO);
			return scds;
		}

		SaleCardStockDaySettlement qry_scds = new SaleCardStockDaySettlement();

		qry_scds.setSaleBranchNo(saleBranchNo);
		qry_scds.setTranDate(lastTranDate);
		qry_scds.setCardFaceId(cardFaceId);

		return saleCardStockDaySettlementDaoImpl
				.getSaleCardStockDaySettlementByKey(qry_scds);
	}

	private List<SaleCardStockDaySettlement> sumAllSaleCardStockDaySettlementByBranch(
			String issueCompanyNo, Date tranDate, String issueBranchNo) {
		List<Object[]> obj_list = saleCardStockDetailDaoImpl
				.sumAllSaleCardStockDaySettlementByBranch(issueCompanyNo,
						tranDate, issueBranchNo);
		// 类型转换
		List<SaleCardStockDaySettlement> all = new ArrayList<SaleCardStockDaySettlement>();
		for (Object[] objarr : obj_list) {
			SaleCardStockDaySettlement icsds = new SaleCardStockDaySettlement();
			icsds.setSaleBranchNo(objarr[0].toString());
			icsds.setTranDate(tranDate);
			icsds.setCardFaceId(new BigInteger(objarr[1].toString()));
			icsds.setLastBalance(BigInteger.ZERO);
			icsds.setTransferIn(new BigInteger(objarr[2].toString()));
			icsds.setTransferOut(new BigInteger(objarr[3].toString()));
			icsds.setSurplusIn(new BigInteger(objarr[4].toString()));
			icsds.setSaleOut(new BigInteger(objarr[5].toString()));
			icsds.setReIssueOut(new BigInteger(objarr[6].toString()));
			icsds.setLossDamageOut(new BigInteger(objarr[7].toString()));
			icsds.setBalance(BigInteger.ZERO);
			all.add(icsds);
		}
		return all;
	}

	/**
	 * 产生发卡商某发卡商分支机构下辖销售分支机构按卡种类面值分组数据
	 * 
	 * @param issueCompanyNo
	 * @param tranDate
	 * @param issueBranchNo
	 * @return
	 */
	private Map<String, SaleCardStockDaySettlement> getAllSaleCardStockDaySettlementByBranchGroup(
			String issueCompanyNo, Date tranDate, String issueBranchNo)
			throws PCPSApplicationException {
		// 取汇总数据
		List<SaleCardStockDaySettlement> asatd_sum_list = sumAllSaleCardStockDaySettlementByBranch(
				issueCompanyNo, tranDate, issueBranchNo);

		Map<String, SaleCardStockDaySettlement> map = new HashMap<String, SaleCardStockDaySettlement>();

		for (SaleCardStockDaySettlement scds : asatd_sum_list) {
			SaleCardStockDaySettlement last_scds = getLastSaleCardStockDaySettlement(
					scds.getSaleBranchNo(), scds.getTranDate(), scds
							.getCardFaceId());
			scds.setLastBalance(last_scds.getBalance());

			// 重新计算本日库存余额
			scds.reCalcBalance();

			map.put(getCardStockDaySettlementKey(scds.getSaleBranchNo(), scds
					.getCardFaceId()), scds);
		}

		return map;
	}

	/**
	 * 删除某发卡商某日某销售分支机构列表的卡库存日结数据(独立事务)
	 * 
	 * @param allSaleBranchNoMap
	 * @param tranDate
	 * @throws PCPSApplicationException
	 */
	private void removeAllSaleCardStockDaySettlementByTranDate(
			Map<String, String> allSaleBranchNoMap, Date tranDate) {

		for (Map.Entry<String, String> sale : allSaleBranchNoMap.entrySet())
			saleCardStockDaySettlementDaoImpl
					.removeAllSaleCardStockDaySettlementByTranDate(sale
							.getKey(), tranDate);
	}

	/**
	 * 删除某发卡商某日某机构列表的凭证库存日结数据(独立事务)
	 * 
	 * @param allBranchNoMap
	 * @param tranDate
	 * @throws PCPSApplicationException
	 */
	private void removeAllVoucherStockDaySettlementByTranDate(
			Map<String, String> allBranchNoMap, Date tranDate) {

		for (Map.Entry<String, String> branch : allBranchNoMap.entrySet())
			voucherStockDaySettlementDaoImpl
					.removeAllVoucherStockDaySettlementByTranDate(branch
							.getKey(), tranDate);
	}

	/**
	 * 创建有效的销售分支机构卡库存日结数据
	 * 
	 * @param asbcds
	 * @throws PCPSApplicationException
	 */
	private void createSaleCardStockDaySettlement(
			SaleCardStockDaySettlement scds) throws PCPSApplicationException {
		if (scds == null)
			return;

		if (BigInteger.ZERO.equals(scds.getLastBalance())
				&& BigInteger.ZERO.equals(scds.getReIssueOut())
				&& BigInteger.ZERO.equals(scds.getSaleOut())
				&& BigInteger.ZERO.equals(scds.getTransferIn())
				&& BigInteger.ZERO.equals(scds.getTransferOut())
				&& BigInteger.ZERO.equals(scds.getSurplusIn())
				&& BigInteger.ZERO.equals(scds.getLossDamageOut())
				&& BigInteger.ZERO.equals(scds.getBalance()))
			return;

		saleCardStockDaySettlementDaoImpl.insert(scds);
	}

	/**
	 * 创建有效的机构凭证库存日结数据
	 * 
	 * @param asbcds
	 * @throws PCPSApplicationException
	 */
	private void createVoucherStockDaySettlement(VoucherStockDaySettlement vsds)
			throws PCPSApplicationException {
		if (vsds == null)
			return;

		if (BigInteger.ZERO.equals(vsds.getLastBalance())
				&& BigInteger.ZERO.equals(vsds.getBuyIn())
				&& BigInteger.ZERO.equals(vsds.getBusinessOut())
				&& BigInteger.ZERO.equals(vsds.getTransferIn())
				&& BigInteger.ZERO.equals(vsds.getTransferOut())
				&& BigInteger.ZERO.equals(vsds.getSurplusIn())
				&& BigInteger.ZERO.equals(vsds.getLossDamageOut())
				&& BigInteger.ZERO.equals(vsds.getBalance()))
			return;

		voucherStockDaySettlementDaoImpl.insert(vsds);
	}

	/**
	 * 产生某发卡商某日某发卡商分支机构下辖销售分支机构的卡库存日结数据
	 * 
	 * @param issueCompanyNo
	 *            发卡商NO
	 * @param tranDate
	 *            帐务日期
	 * @param issueBranchNo
	 *            发卡商分支机构
	 * @throws PCPSApplicationException
	 */
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public void generateSaleCardStockDaySettlement(String issueCompanyNo,
			Date tranDate, String issueBranchNo)
			throws PCPSApplicationException {
		// 干净的日期
		tranDate = PCPSUtil.getZeroedHMS(tranDate);

		// 取汇总数据
		Map<String, SaleCardStockDaySettlement> scds_today = getAllSaleCardStockDaySettlementByBranchGroup(
				issueCompanyNo, tranDate, issueBranchNo);

		// 所有的销售商分支机构
		Map<String, String> allSaleBranchNoMap = getAllSaleBranchNoMapByBranchNo(issueBranchNo);

		// 取所有的卡面图样数据
		Map<BigInteger, BigInteger> allCardFaceIdMap = getAllCardFaceIdMapByIssueCompanyNo(issueCompanyNo);

		// 删除某发卡商某日所有分支机构库存日结数据
		removeAllSaleCardStockDaySettlementByTranDate(allSaleBranchNoMap,
				tranDate);

		String saleBranchNo = null;
		BigInteger cardFaceId = null;
		String key = null;

		// 循环产生
		// 销售商分支机构循环
		for (Map.Entry<String, String> saleBranch : allSaleBranchNoMap
				.entrySet()) {
			saleBranchNo = saleBranch.getKey();
			// 卡种类循环
			for (Map.Entry<BigInteger, BigInteger> cardFace : allCardFaceIdMap
					.entrySet()) {
				cardFaceId = cardFace.getKey();

				key = getCardStockDaySettlementKey(saleBranchNo, cardFaceId);
				SaleCardStockDaySettlement scds = scds_today.remove(key);
				// 当日有数据
				if (scds != null) {
					createSaleCardStockDaySettlement(scds);
					continue;
				}
				// 当日无数据
				Date lastTranDate = saleCardStockDaySettlementDaoImpl
						.getMaxTranDate(saleBranchNo, tranDate, cardFaceId);
				// 前日无数据
				if (lastTranDate == null)
					continue;

				SaleCardStockDaySettlement last_scds = new SaleCardStockDaySettlement();

				last_scds.setTranDate(lastTranDate);
				last_scds.setSaleBranchNo(saleBranchNo);
				last_scds.setCardFaceId(cardFaceId);

				SaleCardStockDaySettlement olast_scds = saleCardStockDaySettlementDaoImpl
						.getSaleCardStockDaySettlementByKey(last_scds);
				if (olast_scds != null) {
					last_scds.setTranDate(tranDate);
					BigInteger lastBalance = olast_scds.getBalance();

					last_scds.setLastBalance(lastBalance);
					last_scds.setTransferIn(BigInteger.ZERO);
					last_scds.setTransferOut(BigInteger.ZERO);
					last_scds.setSurplusIn(BigInteger.ZERO);
					last_scds.setSaleOut(BigInteger.ZERO);
					last_scds.setReIssueOut(BigInteger.ZERO);
					last_scds.setLossDamageOut(BigInteger.ZERO);

					last_scds.setBalance(lastBalance);

					// 迁移前日数据到今日
					createSaleCardStockDaySettlement(last_scds);
				}
			}
		}
	}

	/**
	 * 发卡商分支机构凭证库存日结表KEY
	 * 
	 * @param icsds
	 * @return
	 */
	private String getVoucherStockDaySettlementKey(String branchNo,
			BigInteger voucherId) {
		StringBuilder sb = new StringBuilder();
		sb.append(branchNo);
		sb.append("_");
		sb.append(voucherId);
		return sb.toString();
	}

	/**
	 * 取某机构上日凭证库存日结数据
	 * 
	 * @param branchNo
	 * @param tranDate
	 * @param voucherId
	 * @return
	 */
	private VoucherStockDaySettlement getLastVoucherStockDaySettlement(
			String branchNo, Date tranDate, BigInteger voucherId) {
		Date lastTranDate = voucherStockDaySettlementDaoImpl.getMaxTranDate(
				branchNo, tranDate, voucherId);
		if (lastTranDate == null) {
			VoucherStockDaySettlement scds = new VoucherStockDaySettlement();
			scds.setBalance(BigInteger.ZERO);
			return scds;
		}

		VoucherStockDaySettlement qry_vsds = new VoucherStockDaySettlement();

		qry_vsds.setBranchNo(branchNo);
		qry_vsds.setTranDate(lastTranDate);
		qry_vsds.setVoucherId(voucherId);

		return voucherStockDaySettlementDaoImpl
				.getVoucherStockDaySettlementByKey(qry_vsds);
	}

	/**
	 * 产生发卡商某日按机构、按凭证ID分组汇总数据
	 * 
	 * @param issueCompanyNo
	 * @param tranDate
	 * @param branchNo
	 * @return
	 */
	private Map<String, VoucherStockDaySettlement> getAllVoucherStockDaySettlementByBranchGroup(
			String issueCompanyNo, Date tranDate, String branchNo)
			throws PCPSApplicationException {
		// 取汇总数据
		List<Object[]> o_vsds_sum_list = voucherStockDetailDaoImpl
				.getVoucherStockDaySettlementByBranchNoAndTranDate(
						issueCompanyNo, branchNo, tranDate);

		List<VoucherStockDaySettlement> vsds_list = new ArrayList<VoucherStockDaySettlement>();

		for (Object[] obj : o_vsds_sum_list) {
			VoucherStockDaySettlement vsds = new VoucherStockDaySettlement();

			vsds.setBranchNo(obj[0].toString());
			vsds.setTranDate(tranDate);
			vsds.setVoucherId(new BigInteger(obj[1].toString()));
			vsds.setIssueCompanyNo(issueCompanyNo);
			vsds.setLastBalance(BigInteger.ZERO);
			vsds.setBuyIn(new BigInteger(obj[2].toString()));
			vsds.setTransferIn(new BigInteger(obj[3].toString()));
			vsds.setSurplusIn(new BigInteger(obj[4].toString()));
			vsds.setTransferOut(new BigInteger(obj[5].toString()));
			vsds.setBusinessOut(new BigInteger(obj[6].toString()));
			vsds.setLossDamageOut(new BigInteger(obj[7].toString()));
			vsds.setBalance(BigInteger.ZERO);

			vsds_list.add(vsds);
		}

		Map<String, VoucherStockDaySettlement> map = new HashMap<String, VoucherStockDaySettlement>();

		for (VoucherStockDaySettlement vsds : vsds_list) {
			VoucherStockDaySettlement last_vsds = getLastVoucherStockDaySettlement(
					vsds.getBranchNo(), vsds.getTranDate(), vsds.getVoucherId());
			vsds.setLastBalance(last_vsds.getBalance());

			// 重新计算本日库存余额
			vsds.reCalcBalance();

			map.put(getVoucherStockDaySettlementKey(vsds.getBranchNo(), vsds
					.getVoucherId()), vsds);
		}

		return map;
	}

	/**
	 * 产生某发卡商某日某机构的凭证日结数据
	 * 
	 * @param issueCompanyNo
	 *            发卡商NO
	 * @param tranDate
	 *            帐务日期
	 * @throws PCPSApplicationException
	 */
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public void generateVoucherStockDaySettlement(String issueCompanyNo,
			Date tranDate) throws PCPSApplicationException {
		// 干净的日期
		tranDate = PCPSUtil.getZeroedHMS(tranDate);

		// 取汇总数据
		Map<String, VoucherStockDaySettlement> vsds_today = getAllVoucherStockDaySettlementByBranchGroup(
				issueCompanyNo, tranDate, null);

		Map<String, String> allbrchlist = new HashMap<String, String>();

		// 取所有的销售机构
		List<SaleBranch> sbrchlist = saleBranchDaoImpl
				.getAllSaleBranchByIssueCompanyNo(issueCompanyNo);

		for (SaleBranch sb : sbrchlist)
			allbrchlist.put(sb.getSaleBranchNo(), sb.getSaleBranchNo());

		// 取所有的发卡商分支机构
		List<IssueBranch> ibrchlist = issueBranchDaoImpl
				.getAllIssueBranchByIssueCompanyNo(issueCompanyNo);

		for (IssueBranch sb : ibrchlist)
			allbrchlist.put(sb.getIssueBranchNo(), sb.getIssueBranchNo());

		// 取所有的凭证种类ID数据
		Map<BigInteger, BigInteger> allVoucherIdMap = getAllVoucherIdMapByIssueCompanyNo(issueCompanyNo);

		// 删除某发卡商某日所有机构凭证库存日结数据
		removeAllVoucherStockDaySettlementByTranDate(allbrchlist, tranDate);

		String branchNo = null;
		BigInteger voucherId = null;
		String key = null;

		// 循环产生
		// 机构循环
		for (Map.Entry<String, String> branch : allbrchlist.entrySet()) {
			branchNo = branch.getKey();
			// 凭证种类循环
			for (Map.Entry<BigInteger, BigInteger> voucher : allVoucherIdMap
					.entrySet()) {
				voucherId = voucher.getKey();

				key = getVoucherStockDaySettlementKey(branchNo, voucherId);
				VoucherStockDaySettlement vsds = vsds_today.remove(key);
				// 当日有数据
				if (vsds != null) {
					createVoucherStockDaySettlement(vsds);
					continue;
				}
				// 当日无数据
				Date lastTranDate = voucherStockDaySettlementDaoImpl
						.getMaxTranDate(branchNo, tranDate, voucherId);
				// 前日无数据
				if (lastTranDate == null)
					continue;
				VoucherStockDaySettlement last_vsds = new VoucherStockDaySettlement();

				last_vsds.setTranDate(lastTranDate);
				last_vsds.setBranchNo(branchNo);
				last_vsds.setVoucherId(voucherId);
				VoucherStockDaySettlement olast_scds = voucherStockDaySettlementDaoImpl
						.getVoucherStockDaySettlementByKey(last_vsds);
				if (olast_scds != null) {
					last_vsds.setTranDate(tranDate);
					BigInteger lastBalance = olast_scds.getBalance();

					last_vsds.setIssueCompanyNo(issueCompanyNo);
					last_vsds.setLastBalance(lastBalance);
					last_vsds.setBuyIn(BigInteger.ZERO);
					last_vsds.setTransferIn(BigInteger.ZERO);
					last_vsds.setTransferOut(BigInteger.ZERO);
					last_vsds.setSurplusIn(BigInteger.ZERO);
					last_vsds.setBusinessOut(BigInteger.ZERO);
					last_vsds.setLossDamageOut(BigInteger.ZERO);

					last_vsds.setBalance(lastBalance);

					// 迁移前日数据到今日
					createVoucherStockDaySettlement(last_vsds);
				}
			}
		}
	}

	/**
	 * 将卡事件日志的trantype转换为BranchDaySett的trantype
	 * 
	 * @param stype
	 * @return
	 */
	private String alterTranType(String stype) {
		/**
		 * 03-冻结
		 */
		if (PCPSUtil.compareObject(stype,
				CardEventLog.CARDEVENTLOG_EVENTTYPE_FREEZE))
			return BranchDaySett.TRANTYPE_FREEZE;

		/**
		 * 11-强行解除密码错误锁定
		 */
		if (PCPSUtil.compareObject(stype,
				CardEventLog.CARDEVENTLOG_EVENTTYPE_PWDERRUNLOCK))
			return BranchDaySett.TRANTYPE_PWDUNLOCK;

		/**
		 * 13-解除冻结
		 */
		if (PCPSUtil.compareObject(stype,
				CardEventLog.CARDEVENTLOG_EVENTTYPE_FREEZE_FREE))
			return BranchDaySett.TRANTYPE_FREEZESOLUTION;

		/**
		 * 20–挂失换卡
		 */
		if (PCPSUtil.compareObject(stype,
				CardEventLog.CARDEVENTLOG_EVENTTYPE_LOSSED))
			return BranchDaySett.TRANTYPE_LOSS_REISSUE;

		/**
		 * 21-换发新卡
		 */
		if (PCPSUtil.compareObject(stype,
				CardEventLog.CARDEVENTLOG_EVENTTYPE_CHANGE_CARD))
			return BranchDaySett.TRANTYPE_REISSUE;

		/**
		 * 22-正式挂失
		 */
		if (PCPSUtil.compareObject(stype,
				CardEventLog.CARDEVENTLOG_EVENTTYPE_CARD_LOSS))
			return BranchDaySett.TRANTYPE_LOSS;

		/**
		 * 23-临时挂失
		 */
		if (PCPSUtil.compareObject(stype,
				CardEventLog.CARDEVENTLOG_EVENTTYPE_CARD_TEMP_LOSS))
			return BranchDaySett.TRANTYPE_TEMPORARYLOSS;

		/**
		 * 24-解挂失
		 */
		if (PCPSUtil.compareObject(stype,
				CardEventLog.CARDEVENTLOG_EVENTTYPE_CARD_UN_LOSS))
			return BranchDaySett.TRANTYPE_RELIEVELOSS;

		/**
		 * 30–补磁
		 */
		if (PCPSUtil.compareObject(stype,
				CardEventLog.CARDEVENTLOG_EVENTTYPE_MAGNETIC))
			return BranchDaySett.TRANTYPE_MAGNETIC;

		/**
		 * 40–变更卡种类
		 */
		if (PCPSUtil.compareObject(stype,
				CardEventLog.CARDEVENTLOG_EVENTTYPE_CHANGE_TYPE))
			return BranchDaySett.TRANTYPE_CARDCLASSIC;

		/**
		 * 41–登记或变更实名信息
		 */
		if (PCPSUtil.compareObject(stype,
				CardEventLog.CARDEVENTLOG_EVENTTYPE_CHANGE_OWNER))
			return BranchDaySett.TRANTYPE_REALNAME;

		/**
		 * 50-手工锁定
		 */
		if (PCPSUtil.compareObject(stype,
				CardEventLog.CARDEVENTLOG_EVENTTYPE_MANUAL_LOCK))
			return BranchDaySett.TRANTYPE_LOCK;

		/**
		 * 51-手工解除锁定
		 */
		if (PCPSUtil.compareObject(stype,
				CardEventLog.CARDEVENTLOG_EVENTTYPE_MANUAL_LOCK_FREE))
			return BranchDaySett.TRANTYPE_LOCKFREE;

		/**
		 * 97-密码重置
		 */
		if (PCPSUtil.compareObject(stype,
				CardEventLog.CARDEVENTLOG_EVENTTYPE_RESET_PASSWORD))
			return BranchDaySett.TRANTYPE_RESET_PWD;

		/**
		 * 98-修改密码
		 */
		if (PCPSUtil.compareObject(stype,
				CardEventLog.CARDEVENTLOG_EVENTTYPE_CHANGE_PASSWORD))
			return BranchDaySett.TRANTYPE_MODIFYPASSWD;

		/**
		 * 99-调整有效期
		 */
		if (PCPSUtil.compareObject(stype,
				CardEventLog.CARDEVENTLOG_EVENTTYPE_MODIFY_EXPIRED))
			return BranchDaySett.TRANTYPE_EXPIRED;

		return "UN";
	}

	/**
	 * 获取机构日结数据
	 * 
	 * @param issueCompanyNo
	 *            发卡商号
	 * @param branchNo
	 *            机构号
	 * @param tranDate
	 *            帐务日期
	 * @return
	 */
	private List<BranchDaySett> getBranchDaySettByBranchNoAndTranDate(
			String issueCompanyNo, String branchNo, Date tranDate) {
		List<Object[]> objlist = cardEventLogDaoImpl
				.getBranchDaySettByBranchNoAndTranDate(issueCompanyNo,
						branchNo, tranDate);
		List<BranchDaySett> bdslist = new ArrayList<BranchDaySett>();
		for (Object[] objarr : objlist) {
			BranchDaySett bds = new BranchDaySett();
			bds.setSaleBranchNo(objarr[0].toString());
			bds.setTranDate(tranDate);
			String stype = alterTranType(objarr[1].toString());
			if (PCPSUtil.isEmpty(stype))
				continue;
			bds.setTranType(stype);
			bds.setTranCount(new BigInteger(objarr[2].toString()));
			bds.setCashAmount(BigInteger.ZERO);
			bds.setTranAmount(BigInteger.ZERO);
			bds.setChequeAmount(BigInteger.ZERO);
			bds.setCreditAmount(BigInteger.ZERO);
			bds.setCashFee(new BigInteger(objarr[7].toString()));
			bds.setTranFee(BigInteger.ZERO);
			bds.setChequeFee(BigInteger.ZERO);
			bds.setCreditFee(BigInteger.ZERO);
			bds.setCardFee(new BigInteger(objarr[6].toString()));
			bds.setDiscountFee(new BigInteger(objarr[4].toString()));

			bdslist.add(bds);
		}

		return bdslist;
	}

	/**
	 * 产生某发卡商某发卡机构激活、授信额度账务日结表
	 * 
	 * @param issueCompanyNo
	 * @param tranDate
	 * @throws PCPSApplicationException
	 */
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public void generateCreditDaySettlement(String issueCompanyNo, Date tranDate)
			throws PCPSApplicationException {
		// 干净的日期
		tranDate = PCPSUtil.getZeroedHMS(tranDate);

		// 删除某发卡商当天的激活、授信额度账务日结表
		creditDaySettlementDaoImpl.removeCreditDaySettlement(issueCompanyNo,
				tranDate);

		// 获取发卡商下属所有的发卡机构(key), value为销售机构的sql in语句部分
		Map<String, String> map = saleBranchDaoImpl
				.getSaleBrchMapByIssueCompanyNo(issueCompanyNo);
		if (map == null || map.isEmpty()) {
			return;
		}
		CreditDaySettlement cds = null;
		for (Map.Entry<String, String> entry : map.entrySet()) {
			cds = new CreditDaySettlement();
			cds.setIssueBranchNo(entry.getKey());
			cds.setTranDate(tranDate);
			// 获取上日期初余额
			List<Object[]> dsobj = creditDaySettlementDaoImpl
					.getCreditDaySettlementByBranch(entry.getKey(), PCPSUtil
							.getPackedYMDString(PCPSUtil.getSubductionDays(
									tranDate, -1)));
			if (dsobj != null && dsobj.size() > 0) {
				cds.setLastBalance(new BigInteger(dsobj.get(0)[6].toString()));
			} else {
				cds.setLastBalance(BigInteger.ZERO);
			}
			// 获取本日资金增加和额度使用
			List<Object[]> adobj = creditAccDetailDaoImpl
					.getDeliverAndActivateByIssueBrchNo(entry.getKey(),
							tranDate);
			if (adobj != null && adobj.size() > 0) {
				cds.setDeliver(new BigInteger(adobj.get(0)[0].toString()));
				cds.setActivate(new BigInteger(adobj.get(0)[1].toString()));
			} else {
				cds.setDeliver(BigInteger.ZERO);
				cds.setActivate(BigInteger.ZERO);
			}
			// 某发卡机构本日下辖销售机构所有手续费总和
//			List<Object[]> objList = issueBranchDaoImpl
//					.getIssueBranchFeeForTranDate(issueCompanyNo, entry
//							.getValue(), tranDate);
//			if (objList != null && objList.size() > 0) {
//				cds.setCardFee(new BigInteger(objList.get(0)[0].toString()));
//				cds.setCashFee(new BigInteger(objList.get(0)[1].toString()));
//			} else {
//				cds.setCardFee(BigInteger.ZERO);
//				cds.setCashFee(BigInteger.ZERO);
//			}
			// cds.setFee(branchDaySettDaoImpl.getFeeTotalBySaleBrchNos(entry.getValue(),
			// tranDate));
			cds.setCardFee(BigInteger.ZERO);
			cds.setCashFee(branchDaySettDaoImpl.getFeeTotalBySaleBrchNos(entry.getValue(),PCPSUtil.getStringYMDByDate(tranDate),PCPSUtil.getStringYMDByDate(tranDate)));
			// 授信额度取发卡机构授信额度阀值
			cds.setCredit(issueBranchDaoImpl.getIssueBranchByIssueBranchNo(
					entry.getKey()).getCreditBalance());
			/**
			 * 本期结余:某发卡机构可激活西邮寄卡金额,计算方式为:期初余额+本期资金增加-本期额度使用-本期手续费+授信额度
			 */
			cds.setBalance(cds.getLastBalance().add(cds.getDeliver()).subtract(
					cds.getActivate()));
			// 资金增加
			cds.setCapitalDeposit(bankAccountDetailDaoImpl
					.getVoucherAmountTotalByIssueBranchNo(cds
							.getIssueBranchNo(), PCPSUtil
							.getStringYMDByDate(tranDate)));
			// 插入日结数据
			creditDaySettlementDaoImpl.insert(cds);
		}
	}

	/**
	 * 产生某发卡商某销售机构某日业务日结数据
	 * 
	 * @param issueCompanyNo
	 * @param tranDate
	 * @param saleBranchNo
	 * @param isOfficial
	 * @throws PCPSApplicationException
	 */
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public void generateBranchDaySett(String issueCompanyNo, Date tranDate,
			String saleBranchNo, boolean isOfficial)
			throws PCPSApplicationException {
		// 干净的日期
		tranDate = PCPSUtil.getZeroedHMS(tranDate);

		// 删除某发卡商某日某销售机构的日结数据
		branchDaySettDaoImpl.removeBranchDaySett(saleBranchNo, tranDate);

		// 分组汇总数据
		List<BranchDaySett> mds_list = new ArrayList<BranchDaySett>();

		// 卡特殊业务交易
		List<BranchDaySett> special_list = getBranchDaySettByBranchNoAndTranDate(
				issueCompanyNo, saleBranchNo, tranDate);

		if (special_list != null && !special_list.isEmpty())
			mds_list.addAll(special_list);

		// 销售业务
		List<BranchDaySett_Obj> sale_list_obj = saleOrderPaidDetailDaoImpl
				.getBranchDaySettByBranchNoAndTranDate(saleBranchNo, tranDate);
		if (sale_list_obj != null) {
			BranchDaySett bds = null;
			List<BranchDaySett> sale_list = new ArrayList<BranchDaySett>();
			for (BranchDaySett_Obj bds_obj : sale_list_obj) {
				bds = new BranchDaySett();
				bds.setSaleBranchNo(bds_obj.getSaleBranchNo());
				bds.setTranDate(bds_obj.getTranDate());
				bds.setTranType(bds_obj.getTranType());
				bds.setTranCount(bds_obj.getTranCount());
				bds.setCashAmount(bds_obj.getCashAmount());
				bds.setTranAmount(bds_obj.getTranAmount());
				bds.setCreditAmount(bds_obj.getCreditAmount());
				bds.setChequeAmount(bds_obj.getChequeAmount());
				bds.setCashFee(bds_obj.getCashFee());
				bds.setTranFee(bds_obj.getTranFee());
				bds.setChequeFee(bds_obj.getChequeFee());
				bds.setCreditFee(bds_obj.getCreditFee());
				bds.setCardFee(bds_obj.getCardFee());
				bds.setDiscountFee(bds_obj.getDiscountFee());
				sale_list.add(bds);
			}

			if (!sale_list.isEmpty())
				mds_list.addAll(sale_list);
		}

		// 充值业务
		List<BranchDaySett_Obj> deposit_list_obj = depositOrderPaidDetailDaoImpl
				.getBranchDaySettByBranchNoAndTranDate(saleBranchNo, tranDate);
		if (deposit_list_obj != null) {
			BranchDaySett bds = null;
			List<BranchDaySett> deposit_list = new ArrayList<BranchDaySett>();
			for (BranchDaySett_Obj bds_obj : deposit_list_obj) {
				bds = new BranchDaySett();
				bds.setSaleBranchNo(bds_obj.getSaleBranchNo());
				bds.setTranDate(bds_obj.getTranDate());
				bds.setTranType(bds_obj.getTranType());
				bds.setTranCount(bds_obj.getTranCount());
				bds.setCashAmount(bds_obj.getCashAmount());
				bds.setTranAmount(bds_obj.getTranAmount());
				bds.setCreditAmount(BigInteger.ZERO);
				bds.setChequeAmount(bds_obj.getChequeAmount());
				bds.setCashFee(bds_obj.getCashFee());
				bds.setTranFee(bds_obj.getTranFee());
				bds.setChequeFee(bds_obj.getChequeFee());
				bds.setCreditFee(BigInteger.ZERO);
				bds.setCardFee(bds_obj.getCardFee());
				bds.setDiscountFee(bds_obj.getDiscountFee());
				deposit_list.add(bds);
			}

			if (!deposit_list.isEmpty())
				mds_list.addAll(deposit_list);
		}

		// 赎回业务
		BigInteger[] bis = redempOrderDaoImpl
				.getBranchDaySettByBranchAndTranDate(saleBranchNo, tranDate);
		if (bis != null) {
			if (BigInteger.ZERO.compareTo(bis[0]) != 0
					|| BigInteger.ZERO.compareTo(bis[1]) != 0) {
				BranchDaySett bds = new BranchDaySett();
				bds.setSaleBranchNo(saleBranchNo);
				bds.setTranDate(tranDate);
				bds.setTranType(BranchDaySett.TRANTYPE_REDEMP);
				bds.setTranCount(bis[0]);
				bds.setRedempAmount(bis[1]);
				mds_list.add(bds);
			}
		}

		// 现金上缴
		List<Object[]> cash_list = saleCapitalDetailDaoImpl
				.getBranchDaySettByBranchAndTranDate(saleBranchNo, tranDate);
		if (cash_list != null) {
			BranchDaySett bds = null;
			List<BranchDaySett> cashwithdraw_list = new ArrayList<BranchDaySett>();
			for (Object[] bds_obj : cash_list) {
				bds = new BranchDaySett();
				bds.setSaleBranchNo(bds_obj[0].toString());
				bds.setTranDate(tranDate);
				bds.setTranType(BranchDaySett.TRANTYPE_DELIVERY);
				bds.setTranCount(new BigInteger(bds_obj[1].toString()));
				bds.setCashAmount(new BigInteger(bds_obj[2].toString()));
				bds.setTranAmount(BigInteger.ZERO);
				bds.setCreditAmount(BigInteger.ZERO);
				bds.setChequeFee(BigInteger.ZERO);
				bds.setCashFee(BigInteger.ZERO);
				bds.setTranFee(BigInteger.ZERO);
				bds.setChequeFee(BigInteger.ZERO);
				bds.setCreditFee(BigInteger.ZERO);
				bds.setCardFee(BigInteger.ZERO);
				bds.setDiscountFee(BigInteger.ZERO);
				cashwithdraw_list.add(bds);
			}

			if (!cashwithdraw_list.isEmpty())
				mds_list.addAll(cashwithdraw_list);
		}

		BigInteger cashFeeTotal = BigInteger.ZERO;

		// 如果存在数据
		if (mds_list != null && mds_list.size() > 0) {
			// 业务汇总数据进入机构日结表
			for (BranchDaySett mds : mds_list) {
				branchDaySettDaoImpl.insert(mds);
				// 计算累计费
				if (mds.getCashFee() != null)
					cashFeeTotal = cashFeeTotal.add(mds.getCashFee());
			}
		}

		// 销售机构相关字段更新
		SaleBranch saleBranch = saleBranchDaoImpl
				.getSaleBranchForUpdate(saleBranchNo);

		// 如果正式轧帐
		if (isOfficial)
			saleBranch.setDayOff(SaleBranch.In_DayOff);

		BigInteger acc = saleBranch.getAlreadyCheckCash();
		if (acc == null)
			acc = BigInteger.ZERO;

		if (saleBranch.getLastCashFee() == null)
			saleBranch.setLastCashFee(BigInteger.ZERO);

		// 检查上次轧帐日期
		Date lcfd = saleBranch.getLastCashFeeDate();
		if (lcfd != null && tranDate.compareTo(lcfd) < 0)
			throw new PCPSApplicationException("", String.format(
					"机构%s上次轧帐日期非法!", saleBranchNo));

		// 如果未发生日期变更
		if (PCPSUtil.compareObject(lcfd, tranDate))
			acc = acc.add(saleBranch.getLastCashFee());

		saleBranch.setAlreadyCheckCash(acc.subtract(cashFeeTotal));
		saleBranch.setLastCashFee(cashFeeTotal);
		saleBranch.setLastCashFeeDate(tranDate);

		saleBranchDaoImpl.updateSaleBranch(saleBranch);
	}

	/**
	 * 产生某销售机构凭证日结数据
	 * 
	 * @param issueCompanyNo
	 * @param tranDate
	 * @param saleBranchNo
	 * @throws PCPSApplicationException
	 */
	private void generateSaleBranchVoucherStockDaySettlement(
			String issueCompanyNo, Date tranDate, String saleBranchNo)
			throws PCPSApplicationException {
		// 干净的日期
		tranDate = PCPSUtil.getZeroedHMS(tranDate);

		// 取汇总数据
		Map<String, VoucherStockDaySettlement> vsds_today = getAllVoucherStockDaySettlementByBranchGroup(
				issueCompanyNo, tranDate, saleBranchNo);

		Map<String, String> allbrchlist = new HashMap<String, String>();

		allbrchlist.put(saleBranchNo, saleBranchNo);

		// 取所有的凭证种类ID数据
		Map<BigInteger, BigInteger> allVoucherIdMap = getAllVoucherIdMapByIssueCompanyNo(issueCompanyNo);

		// 删除某发卡商某日map中所有机构凭证库存日结数据
		removeAllVoucherStockDaySettlementByTranDate(allbrchlist, tranDate);

		String branchNo = null;
		BigInteger voucherId = null;
		String key = null;

		// 循环产生
		// 机构循环
		for (Map.Entry<String, String> branch : allbrchlist.entrySet()) {
			branchNo = branch.getKey();
			// 凭证种类循环
			for (Map.Entry<BigInteger, BigInteger> voucher : allVoucherIdMap
					.entrySet()) {
				voucherId = voucher.getKey();

				key = getVoucherStockDaySettlementKey(branchNo, voucherId);
				VoucherStockDaySettlement vsds = vsds_today.remove(key);
				// 当日有数据
				if (vsds != null) {
					createVoucherStockDaySettlement(vsds);
					continue;
				}
				// 当日无数据
				Date lastTranDate = voucherStockDaySettlementDaoImpl
						.getMaxTranDate(branchNo, tranDate, voucherId);
				// 前日无数据
				if (lastTranDate == null)
					continue;
				VoucherStockDaySettlement last_vsds = new VoucherStockDaySettlement();

				last_vsds.setTranDate(lastTranDate);
				last_vsds.setBranchNo(branchNo);
				last_vsds.setVoucherId(voucherId);
				VoucherStockDaySettlement olast_scds = voucherStockDaySettlementDaoImpl
						.getVoucherStockDaySettlementByKey(last_vsds);
				if (olast_scds != null) {
					last_vsds.setTranDate(tranDate);
					BigInteger lastBalance = olast_scds.getBalance();

					last_vsds.setIssueCompanyNo(issueCompanyNo);
					last_vsds.setLastBalance(lastBalance);
					last_vsds.setBuyIn(BigInteger.ZERO);
					last_vsds.setTransferIn(BigInteger.ZERO);
					last_vsds.setTransferOut(BigInteger.ZERO);
					last_vsds.setSurplusIn(BigInteger.ZERO);
					last_vsds.setBusinessOut(BigInteger.ZERO);
					last_vsds.setLossDamageOut(BigInteger.ZERO);

					last_vsds.setBalance(lastBalance);

					// 迁移前日数据到今日
					createVoucherStockDaySettlement(last_vsds);
				}
			}
		}
	}

	/**
	 * 销售机构日终轧帐
	 * 
	 * @param issueCompanyNo
	 * @param tranDate
	 * @param saleBranchNo
	 * @param isOfficial
	 * @throws PCPSApplicationException
	 */
	public void saleBranchDayOffSett(String issueCompanyNo, Date tranDate,
			String saleBranchNo, boolean isOfficial)
			throws PCPSApplicationException {
		// step 1: 卡库存轧帐
		generateSaleCardStockDaySettlement(issueCompanyNo, tranDate,
				saleBranchNo);

		// step 2: 凭证库轧帐
		generateSaleBranchVoucherStockDaySettlement(issueCompanyNo, tranDate,
				saleBranchNo);

		// step 3: 业务轧帐
		generateBranchDaySett(issueCompanyNo, tranDate, saleBranchNo,
				isOfficial);
	}

	/**
	 * 删除某发卡商某日所有商户的日结数据
	 * 
	 * @param issueCompanyNo
	 *            发卡商号
	 * @param tranDate
	 *            帐务日期
	 */
	private void removeAllMerchantDaySettlementByTranDate(
			String issueCompanyNo, Date tranDate) {
		merchantDaySettlementDaoImpl.removeAllMerchantDaySettlementByTranDate(
				issueCompanyNo, tranDate);
	}

	/**
	 * 产生某发卡商某日按商户的日结数据
	 * 
	 * @param issueCompanyNo
	 *            发卡商NO
	 * @param tranDate
	 *            帐务日期
	 * @throws PCPSApplicationException
	 */
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public void generateMerchantDaySettlement(String issueCompanyNo,
			Date tranDate) throws PCPSApplicationException {
		// 干净的日期
		tranDate = PCPSUtil.getZeroedHMS(tranDate);

		// 删除某发卡商某日所有商户的日结数据
		removeAllMerchantDaySettlementByTranDate(issueCompanyNo, tranDate);

		// 分组汇总数据
		List<MerchantDaySettlement> mds_list = mchTradDetailDaoImpl
				.getAllMerchantDaySettlementByMerchantNo(issueCompanyNo, null,
						tranDate);

		PCPSUtil.Log(String.format("MerchantDaySettlement[%s][%d]",
				issueCompanyNo, mds_list == null ? 0 : mds_list.size()));

		// // 如果查无数据
		// if (mds_list == null || mds_list.size() < 1)
		// return;

		for (MerchantDaySettlement mds : mds_list)
			merchantDaySettlementDaoImpl.insert(mds);

		// 插入后检查该日数据，如有商户没有数据说明该商户该日未做交易，需要插入一个各项为0的记录。
		// 根据发卡商编号得到商户集合后遍历，如果该商户在结算表里无数据，且已激活，则插入一条各项为0的数据。
		List<Merchant> merchants = merchantDaoImpl
				.getMerchantListByIssueCompanyNo(issueCompanyNo);
		for (Merchant m : merchants) {
			if (merchantDaySettlementDaoImpl
					.getMerchantDaySettlementByTranDate_Merchantno(m
							.getMerchantNo(), tranDate) == null
					&& m.getActivate().equals(Merchant.MERCHANT_ACTIVATE)) {
				MerchantDaySettlement mds_0 = new MerchantDaySettlement();
				mds_0.setIssueCompanyNo(issueCompanyNo);
				mds_0.setMerchantNo(m.getMerchantNo());
				mds_0.setTranDate(tranDate);
				mds_0.setCancelPaid(BigInteger.ZERO);
				mds_0.setCancelPaidCount(BigInteger.ZERO);
				mds_0.setConsume(BigInteger.ZERO);
				mds_0.setOtherPaid(BigInteger.ZERO);
				mds_0.setConsumeCount(BigInteger.ZERO);
				mds_0.setDeposit(BigInteger.ZERO);
				mds_0.setDepositCount(BigInteger.ZERO);
				mds_0.setFee(BigInteger.ZERO);
				mds_0.setOtherPaid(BigInteger.ZERO);

				merchantDaySettlementDaoImpl.insert(mds_0);
			}

		}
	}

	/**
	 * 删除某发卡商某日所有商户按业务类型的日结数据
	 * 
	 * @param issueCompanyNo
	 *            发卡商号
	 * @param tranDate
	 *            帐务日期
	 */
	private void removeAllMerchantBusinessDaySettlementByTranDate(
			String issueCompanyNo, Date tranDate) {
		merchantBusinessDaySettlementDaoImpl
				.removeAllMerchantBusinessDaySettlementByTranDate(
						issueCompanyNo, tranDate);
	}

	/**
	 * 产生某发卡商某日按商户及业务类型的日结数据
	 * 
	 * @param issueCompanyNo
	 *            发卡商NO
	 * @param tranDate
	 *            帐务日期
	 * @throws PCPSApplicationException
	 */
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public void generateMerchantBusinessDaySettlement(String issueCompanyNo,
			Date tranDate) throws PCPSApplicationException {
		// 干净的日期
		tranDate = PCPSUtil.getZeroedHMS(tranDate);

		// 删除某发卡商某日所有商户的日结数据
		removeAllMerchantBusinessDaySettlementByTranDate(issueCompanyNo,
				tranDate);

		// 分组汇总数据
		List<MerchantBusinessDaySettlement> mds_list = mchBsTypeTradDetailDaoImpl
				.getAllMerchantBusinessDaySettlementByMerchantNo(
						issueCompanyNo, null, tranDate);

		PCPSUtil.Log(String.format("MerchantBusinessDaySettlement[%s][%d]",
				issueCompanyNo, mds_list == null ? 0 : mds_list.size()));

		// 如果查无数据
		if (mds_list == null || mds_list.size() < 1)
			return;

		for (MerchantBusinessDaySettlement mds : mds_list)
			merchantBusinessDaySettlementDaoImpl.insert(mds);
	}

	/**
	 * 产生某发卡商某日某商户的按销售机构日结数据
	 * 
	 * @param issueCompanyNo
	 *            发卡商NO
	 * @param tranDate
	 *            帐务日期
	 * @param merchantNo
	 *            商户号
	 * @throws PCPSApplicationException
	 */
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public void generateIncomeDaySettlementByMerchantNo(String issueCompanyNo,
			Date tranDate, String merchantNo) throws PCPSApplicationException {
		// 干净的日期
		tranDate = PCPSUtil.getZeroedHMS(tranDate);

		// 删除某发卡商某日某商户所有的按销售机构日结数据
		incomeDaySettlementDaoImpl.removeAllIncomeDaySettlementByMerchantNo(
				issueCompanyNo, merchantNo, tranDate);

		// 分组汇总数据
		List<IncomeDaySettlement> ids_list = mchAccDetailDaoImpl
				.getAllIncomeDaySettlementByMerchantNo(merchantNo, tranDate);

		// 如果查无数据
		if (ids_list == null || ids_list.size() < 1)
			return;

		// 取商户的收益机构
		Merchant merchant = merchantDaoImpl.getMerchantByMerchantNo(merchantNo);

		for (IncomeDaySettlement ids : ids_list) {
			// 取销售机构的收益机构
			SaleBranch saleBranch = saleBranchDaoImpl
					.getSaleBranchBySaleBranchNo(ids.getSaleBranchNo());
			ids.setIssueCompanyNo(issueCompanyNo);
			ids.setMerchantNo(merchantNo);
			ids.setTranDate(tranDate);
			ids.setMIncomeBranchId(merchant.getIncomeBranchId());
			ids.setSIncomeBranchId(saleBranch.getIncomeBranchId());
			incomeDaySettlementDaoImpl.insert(ids);
		}
	}

	/**
	 * 取下一日
	 * 
	 * @param cur
	 * @return
	 */
	private Date getNextDate(Date cur) {
		java.util.Calendar cal = java.util.Calendar.getInstance();
		cal.setTime(PCPSUtil.getZeroedHMS(cur));
		cal.add(java.util.Calendar.DAY_OF_MONTH, 1);
		return cal.getTime();
	}

	/**
	 * 处理某商户某日的对帐控制
	 * 
	 * @param merchant
	 * @param checkDate
	 * @param hastran
	 * @param isForce
	 * @throws PCPSApplicationException
	 */
	private void handleMerchantChkAccCtl(Merchant merchant, Date checkDate,
			boolean hastran, boolean isForce) throws PCPSApplicationException {
		// 判断是否有对帐控制
		MchChkAccCtl mcac = mchChkAccCtlDaoImpl.getMchChkAccCtlByKey(merchant
				.getMerchantNo(), checkDate);
		String sCheckDate = PCPSUtil.getStringYMDByDate(checkDate);
		// 如果存在则跳过
		if (mcac != null) {
			// 如为强行日切则返回
			if (isForce)
				return;
			// 该商户是否需要对帐,如商户无需对帐则返回
			if (PCPSUtil.compareObject(merchant.getCheckAccMode(),
					Merchant.CHECKACCMODE_NOACC))
				return;
			// 判断是否平帐,如平帐则返回
			if (PCPSUtil.compareObject(mcac.getCheckResult(),
					MchChkAccCtl.CHECKRESULT_SUCC))
				return;
			// 帐不平,如强行日切则返回,否则拋异常
			if (!isForce)
				throw new PCPSApplicationException("", String
						.format("商户%s帐务日期%s尚未平帐!", merchant.getMerchantNo(),
								sCheckDate));
		}

		// 该商户是否需要对帐
		if (PCPSUtil.compareObject(merchant.getCheckAccMode(),
				Merchant.CHECKACCMODE_MERCHANT)) {
			if (!isForce)
				throw new PCPSApplicationException("", String
						.format("商户%s帐务日期%s尚未核对!", merchant.getMerchantNo(),
								sCheckDate));
		}

		// 如果无交易,则自动插入一条对帐成功记录
		mcac = new MchChkAccCtl();

		mcac.setMerchantNo(merchant.getMerchantNo());
		mcac.setCheckDate(checkDate);
		mcac.setCheckResult(hastran ? MchChkAccCtl.CHECKRESULT_NOCHECK
				: MchChkAccCtl.CHECKRESULT_SUCC);
		mcac.setCheckFileId(null);
		mcac.setDebitCount(BigInteger.ZERO);
		mcac.setDebitAmt(BigInteger.ZERO);
		mcac.setCreditCount(BigInteger.ZERO);
		mcac.setCreditAmt(BigInteger.ZERO);

		if (!hastran) {
			// 插入记录
			mchChkAccCtlDaoImpl.insert(mcac);
			return;
		}
		/*
		 * // 从POS对帐表中汇总 TerminalSettlement ts = terminalSettlementDaoImpl
		 * .sumAllTerminalSettlementByMerchantAndTranDate(merchant
		 * .getMerchantNo(), checkDate); if (ts == null) { // 插入记录
		 * mchChkAccCtlDaoImpl.insert(mcac); return; } // 设置汇总数据
		 * mcac.setDebitCount(ts.getDebitCount());
		 * mcac.setDebitAmt(ts.getDebitAmount());
		 * mcac.setCreditCount(ts.getCreditCount());
		 * mcac.setCreditAmt(ts.getCreditAmount()); // 如果是POS商户,则自动产生
		 * MrchSettResult msr = mchTradDetailDaoImpl
		 * .getMrchSettResultByMerchantNo(merchant.getMerchantNo(), checkDate);
		 * 
		 * if (msr == null) throw new PCPSApplicationException("",
		 * String.format( "自动产生商户%s帐务日期%s汇总数据错!", merchant.getMerchantNo(),
		 * sCheckDate));
		 * 
		 * if (PCPSUtil.compareObject(ts.getDebitCount(), msr.DebitCount) &&
		 * PCPSUtil.compareObject(ts.getDebitAmount(), msr.DebitAmount) &&
		 * PCPSUtil.compareObject(ts.getCreditCount(), msr.CreditCount) &&
		 * PCPSUtil.compareObject(ts.getCreditAmount(), msr.CreditAmount))
		 * mcac.setCheckResult(MchChkAccCtl.CHECKRESULT_SUCC);
		 */
		// 插入记录
		mchChkAccCtlDaoImpl.insert(mcac);
	}

	/**
	 * 设置发卡商状态
	 * 
	 * @param issueCompanyNo
	 * @param status
	 * @param dayOffStatus
	 * @param dayOffRemark
	 * @return
	 */
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public boolean switchDayOffStatus(String issueCompanyNo, String status,
			String dayOffStatus, String dayOffRemark) {
		IssueCompany issueCompany = issueCompanyDaoImpl
				.getIssueCompanyByIssueCompanyNo(issueCompanyNo);

		if (issueCompany == null)
			return false;

		if (!PCPSUtil.isEmpty(status))
			issueCompany.setStatus(status);

		issueCompany.setDayOffStatus(dayOffStatus);
		issueCompany.setDayOffRemark(dayOffRemark);

		PCPSUtil.Log("[" + issueCompanyNo + "]" + dayOffRemark + " ...");

		try {
			issueCompanyDaoImpl.updateIssueCompany(issueCompany);
			return true;
		} catch (Exception e) {
		}

		return false;
	}

	/**
	 * 商户日切
	 * 
	 * @param merchantNo
	 *            商户号
	 * @param isForce
	 *            是否强行日切
	 * @throws PCPSApplicationException
	 */
	public void merchantDayOff(String merchantNo, boolean isForce)
			throws PCPSApplicationException {
		// 取商户
		Merchant merchant = merchantDaoImpl.getMerchantForUpdate(merchantNo);
		if (merchant == null)
			throw new PCPSApplicationException("", String.format("无此商户%s!",
					merchantNo));

		// 取发卡商
		IssueCompany issueCompany = issueCompanyDaoImpl
				.getIssueCompanyByIssueCompanyNo(merchant.getIssueCompanyNo());
		if (issueCompany == null)
			throw new PCPSApplicationException("", String.format("无此发卡商%s!",
					merchant.getIssueCompanyNo()));

		// 商户帐务日期
		Date mTranDate = PCPSUtil.getZeroedHMS(merchant.getTranDate());

		// 发卡商帐务日期
		Date iTranDate = PCPSUtil.getZeroedHMS(issueCompany.getTranDate());

		// 如果商户帐务日期已经超过了发卡商帐务日期,则无需切换
		if (mTranDate.compareTo(iTranDate) > 0)
			return;

		// 是否有交易
		boolean hastran = mchAccDetailDaoImpl.merchantHasTransaction(
				merchantNo, mTranDate, iTranDate);

		// 商户在此时间段内没有交易
		if (!hastran) {
			merchant.setTranDate(getNextDate(iTranDate));
			merchantDaoImpl.updateMerchant(merchant);
			return;
		}

		while (mTranDate.compareTo(iTranDate) <= 0) {
			// 检查当日该商户是否有交易
			hastran = mchAccDetailDaoImpl.merchantHasTransaction(merchantNo,
					mTranDate, mTranDate);
			// 处理商户对帐控制
			handleMerchantChkAccCtl(merchant, mTranDate, hastran, isForce);
			// 日期+1
			mTranDate = getNextDate(mTranDate);
		}

		// 执行该商户日切
		merchant.setTranDate(getNextDate(iTranDate));
		merchantDaoImpl.updateMerchant(merchant);
	}

	/**
	 * 发卡商日切
	 * 
	 * @param issueCompanyNo
	 *            发卡商NO
	 * @throws PCPSApplicationException
	 */
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public void switchIssueCompany(String issueCompanyNo)
			throws PCPSApplicationException {
		IssueCompany issueCompany = issueCompanyDaoImpl
				.getIssueCompanyByIssueCompanyNo(issueCompanyNo);

		if (issueCompany == null)
			throw new PCPSApplicationException("", String.format("无此发卡商%s!",
					issueCompanyNo));

		if (PCPSUtil.compareObject(issueCompany.getStatus(),
				IssueCompany.ISSUECOMPANY_NORMAL_ENDDAY))
			throw new PCPSApplicationException("", String.format("发卡商%s正在日终!",
					issueCompanyNo));

		// 日终日期
		Date tranDate = PCPSUtil.getZeroedHMS(issueCompany.getTranDate());

		// 日终后日期
		Date newTranDate = getNextDate(tranDate);

		// 取所有的商户
		List<Merchant> mchlist = merchantDaoImpl
				.getMerchantListByIssueCompanyNo(issueCompanyNo);

		// 所有激活的商户的帐务日期均应大于发卡商的帐务日期
		for (Merchant mch : mchlist) {
			// 以锁定方式重新检索
			Merchant mrch = merchantDaoImpl.getMerchantForUpdate(mch
					.getMerchantNo());
			int result = mrch.getTranDate().compareTo(tranDate);
			if (result <= 0)
				throw new PCPSApplicationException("", String.format(
						"商户%s帐务日期有误或未日切!", mrch.getMerchantNo()));
		}

		issueCompany.setStatus(IssueCompany.ISSUECOMPANY_NORMAL_ENDDAY);
		issueCompany.setTranDate(newTranDate);

		issueCompany.setDayOffStatus(DayOffImpl.DAYOFF_STEP_START);
		issueCompany.setDayOffRemark("准备开始日终...");

		// 置日终状态
		issueCompanyDaoImpl.updateIssueCompany(issueCompany);

		PCPSUtil.Log(String.format("[%s]准备开始日终...", issueCompanyNo));
	}

	/**
	 * 开始日终
	 * 
	 * @param issueCompanyNo
	 */
	public void startDayOff(String issueCompanyNo)
			throws PCPSApplicationException {
		QueueConnection cnn = null;
		QueueSender sender = null;
		QueueSession sess = null;
		Queue queue = null;

		PCPSUtil.setDayOffLogEntry(issueCompanyNo);

		// 置发卡商日终标志
		daySettlementBusinessImpl.switchIssueCompany(issueCompanyNo);

		// Properties props = new Properties();
		// props.put(Context.INITIAL_CONTEXT_FACTORY,
		// "weblogic.jndi.WLInitialContextFactory");
		// props.put(Context.PROVIDER_URL, "t3://localhost:7001");
		try {
			InitialContext ctx = new InitialContext();
			QueueConnectionFactory factory = (QueueConnectionFactory) ctx
					.lookup("weblogic.jms.ConnectionFactory");
			cnn = factory.createQueueConnection();
			sess = cnn.createQueueSession(false,
					QueueSession.CLIENT_ACKNOWLEDGE);
			queue = (Queue) ctx.lookup(DayOffImpl.DAYOFF_QUEUE_NAME);
			TextMessage msg = sess.createTextMessage(issueCompanyNo);
			sender = sess.createSender(queue);
			sender.send(msg);
			sess.close();
			cnn.close();
			PCPSUtil.Log("启动日终成功...");
		} catch (Exception e) {
			throw new PCPSApplicationException("", "启动日终失败!");
		}
	}

}